home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / JTable.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  162.8 KB  |  4,530 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)JTable.java    1.110 98/09/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package javax.swing;
  16.  
  17. import java.util.*;
  18.  
  19. import java.awt.*;
  20. import java.awt.event.*;
  21.  
  22. import java.beans.*;
  23.  
  24. import java.io.Serializable;
  25. import java.io.ObjectOutputStream;
  26. import java.io.ObjectInputStream;
  27. import java.io.IOException;
  28.  
  29. import javax.accessibility.*;
  30.  
  31. import javax.swing.event.*;
  32. import javax.swing.plaf.*;
  33. import javax.swing.table.*;
  34. import javax.swing.border.*;
  35.  
  36. import java.text.DateFormat;
  37. import java.text.NumberFormat; 
  38.  
  39. /**
  40.  * JTable is a user-interface component that presents data in a two-dimensional
  41.  * table format. The JTable has many facilities that make it possible to
  42.  * customize its rendering and editing but provides defaults
  43.  * for these features so that simple tables can be set up easily.
  44.  * For example, to set up a table with 10 rows and 10 columns of numbers:
  45.  * <p>
  46.  * <pre>
  47.  *      TableModel dataModel = new AbstractTableModel() {
  48.  *          public int getColumnCount() { return 10; }
  49.  *          public int getRowCount() { return 10;}
  50.  *          public Object getValueAt(int row, int col) { return new Integer(row*col); }
  51.  *      };
  52.  *      JTable table = new JTable(dataModel);
  53.  *      JScrollPane scrollpane = new JScrollPane(table);
  54.  * </pre>
  55.  * <p>
  56.  * Because the JTable is now much easier to set up with custom models
  57.  * the DefaultTableModel is less useful than it was in previous releases.
  58.  * Instead of copying the data in an application into the DefaultTableModel,
  59.  * we recommend wrapping it in the methods of the TableModel interface and
  60.  * passing the real data to the JTable as above. This technique is nearly as concise
  61.  * as using a DefaultTableModel and starting this way has a number of advantages
  62.  * over the longer term. In particular: it is a scalable technique,
  63.  * is easier to handle dynamic or editable tables and often results in much
  64.  * more efficient applications because the model is free to choose the
  65.  * internal representation that best suits the data.
  66.  * <p>
  67.  * The "Table" directory in the examples/demo area gives a number of complete
  68.  * examples of JTable usage, covering how the JTable can be used to provide
  69.  * an editable view of data taken from a database and how to modify the columns
  70.  * in the display to use specialized renderers and editors. For example, overriding
  71.  * AbstractTableModel's <code>getColumnClass()</code> method to return a value of
  72.  * <code>ImageIcon.class</code> for a given column allows icons to be displayed,
  73.  * while returning a value of <code>Number.class</code> allows digits to be
  74.  * right-justified in the column.
  75.  * <p>
  76.  * The JTable uses integers exclusively to refer to both the rows and the columns
  77.  * of the model that it displays. The JTable simply takes a tabular range of cells
  78.  * and uses <code>getValueAt(int, int)</code> to retrieve and display the appropriate
  79.  * values from the model.
  80.  * <p>
  81.  * If <code>getTableHeader().setReorderingAllowed(boolean)</code> is used to
  82.  * enable column reordering columns may be rearranged in the JTable so that the
  83.  * view's columns appear in a different order to the columns in the model.
  84.  * This does not affect the implementation of the model at all: when the
  85.  * columns are reordered, the JTable maintains the new order of the columns
  86.  * internally and converts its column indices before querying the model.
  87.  * <p>
  88.  * So, when writing a TableModel, it is not necessary to listen for column
  89.  * reordering events as the the model will be queried in its own co-ordinate
  90.  * system regardless of what is happening in the view.
  91.  * In the examples area there is a demonstration of a sorting algorithm making
  92.  * use of exactly this technique to interpose yet another co-ordinate system
  93.  * where the order of the rows is changed, rather than the order of the columns.
  94.  * <p>
  95.  * The general rule for the JTable API and the APIs of all its associated classes,
  96.  * including the the column model and both the row and column selection models, is:
  97.  * methods using integer indices for rows and columns always use the co-ordinate
  98.  * system of the view. There are three exceptions to this rule:
  99.  * <ul>
  100.  * <li> All references to rows and columns in the TableModel
  101.  *      interface are in the co-ordinate system of the model.
  102.  * <li> The index <I>modelIndex</I> in the TableColumn constructors
  103.  *      refers to the index of the column in the model, not the view.
  104.  * <li> All constructors for the TableModelEvent, which describes changes
  105.  *      that have taken place in a table model, use the co-ordinate system
  106.  *      of the model.
  107.  * </ul>
  108.  * The TableColumn provides a slot for holding an identifier or "tag" for each column
  109.  * and the JTable and TableColumModel both support <I>getColumn(Object id)</I>
  110.  * conveniences for locating columns by their identifier. If no identifier is
  111.  * explicitly set, the TableColumn returns its header value (the name of the column)
  112.  * as a default. A different identifier, which can be of any type, can be set
  113.  * using the TableColumn's <I>setIdentifier()</I> method. All of the JTable's
  114.  * functions operate correctly regardless of the type and uniqueness of these
  115.  * identifiers.
  116.  * <p>
  117.  * The <I>convertColumnIndexToView()</I> and
  118.  * <I>convertColumnIndexToModel()</I> methods have been provided to
  119.  * convert between the two co-ordinate systems but
  120.  * they are rarely needed during normal use.
  121.  * <p>
  122.  * Like all JComponent classes, you can use
  123.  * {@link JComponent#registerKeyboardAction} to associate an
  124.  * {@link Action} object with a {@link KeyStroke} and execute the
  125.  * action under specified conditions.
  126.  * <p>
  127.  * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/table.html">How to Use Tables</a>
  128.  * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  129.  * for further documentation.
  130.  * <p>
  131.  * For the keyboard keys used by this component in the standard Look and
  132.  * Feel (L&F) renditions, see the
  133.  * <a href="doc-files/Key-Index.html#JTable">JTable</a> key assignments.
  134.  * <p>
  135.  * <strong>Warning:</strong>
  136.  * Serialized objects of this class will not be compatible with
  137.  * future Swing releases.  The current serialization support is appropriate
  138.  * for short term storage or RMI between applications running the same
  139.  * version of Swing.  A future release of Swing will provide support for
  140.  * long term persistence.
  141.  *
  142.  *
  143.  * @beaninfo
  144.  *   attribute: isContainer false
  145.  *
  146.  * @version 1.110 09/18/98
  147.  * @author Philip Milne
  148.  * @author Alan Chung
  149.  */
  150. public class JTable extends JComponent implements TableModelListener, Scrollable,
  151.     TableColumnModelListener, ListSelectionListener, CellEditorListener,
  152.     Accessible
  153. {
  154. //
  155. // Static Constants
  156. //
  157.  
  158.     /**
  159.      * @see #getUIClassID
  160.      * @see #readObject
  161.      */
  162.     private static final String uiClassID = "TableUI";
  163.  
  164.     /** Do not adjust column widths automatically, use a scrollbar */
  165.     public static final int     AUTO_RESIZE_OFF = 0;
  166.  
  167.     /** When a column is adjusted in the UI, adjust the next column the opposite way */
  168.     public static final int     AUTO_RESIZE_NEXT_COLUMN = 1;
  169.  
  170.     /** During UI adjustment, change subsequent columns to preserve the total width */
  171.     public static final int     AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
  172.  
  173.     /** During all resize operations, apply adjustments to the last column only */
  174.     public static final int     AUTO_RESIZE_LAST_COLUMN = 3;
  175.  
  176.     /** During all resize operations, proportionately resize all columns */
  177.     public static final int     AUTO_RESIZE_ALL_COLUMNS = 4;
  178.  
  179.  
  180. //
  181. // Instance Variables
  182. //
  183.  
  184.     /** The TableModel of the table */
  185.     protected TableModel        dataModel;
  186.  
  187.     /** The TableColumnModel of the table */
  188.     protected TableColumnModel  columnModel;
  189.  
  190.     /** The ListSelectionModel of the table, used to keep track of row selections */
  191.     protected ListSelectionModel selectionModel;
  192.  
  193.     /** The TableHeader working with the table */
  194.     protected JTableHeader      tableHeader;
  195.  
  196.     /** The height of all rows in the table */
  197.     protected int               rowHeight;
  198.  
  199.     /** The height margin between rows */
  200.     protected int               rowMargin;
  201.  
  202.     /** The color of the grid */
  203.     protected Color             gridColor;
  204.  
  205.     /** The table draws horizontal lines between cells if showHorizontalLines is true */
  206.     protected boolean           showHorizontalLines;
  207.  
  208.     /** The table draws vertical lines between cells if showVerticalLines is true */
  209.     protected boolean           showVerticalLines;
  210.  
  211.     /**
  212.      *  This mode value determines if table automatically resizes the
  213.      *  width the table's columns to take up the entire width of the
  214.      *  table, and how it does the resizing.
  215.      */
  216.     protected int               autoResizeMode;
  217.  
  218.     /**
  219.      *  The table will query the TableModel to build the default
  220.      *  set of columns if this is true.
  221.      */
  222.     protected boolean           autoCreateColumnsFromModel;
  223.  
  224.     /** Used by the Scrollable interface to determine the initial visible area */
  225.     protected Dimension         preferredViewportSize;
  226.  
  227.     /** Row selection allowed in this table */
  228.     protected boolean           rowSelectionAllowed;
  229.  
  230.     /**
  231.      * If this is true, then both a row selection and a column selection
  232.      * can be non-empty at the same time, the selected cells are the
  233.      * the cells whose row and column are both selected.
  234.      */
  235.     protected boolean           cellSelectionEnabled;
  236.  
  237.     /** If editing, Component that is handling the editing. */
  238.     transient protected Component       editorComp;
  239.  
  240.     /**
  241.      * The object that overwrites the screen real estate occupied by the
  242.      * current cell and allows the user to change those contents.
  243.      */
  244.     transient protected TableCellEditor cellEditor;
  245.  
  246.     /** Identifies the column of the cell being edited. */
  247.     transient protected int             editingColumn;
  248.  
  249.     /** Identifies the row of the cell being edited. */
  250.     transient protected int             editingRow;
  251.  
  252.     /**
  253.      * A table of objects that display the contents of a cell,
  254.      * indexed by class.
  255.      */
  256.     transient protected Hashtable defaultRenderersByColumnClass;
  257.  
  258.     /**
  259.      * A table of objects that display and edit the contents of a cell,
  260.      * indexed by class.
  261.      */
  262.     transient protected Hashtable defaultEditorsByColumnClass;
  263.  
  264.     /** The foreground color of selected cells */
  265.     protected Color selectionForeground;
  266.  
  267.     /** The background color of selected cells */
  268.     protected Color selectionBackground;
  269.  
  270. //
  271. // Constructors
  272. //
  273.  
  274.     /**
  275.      * Constructs a default JTable which is initialized with a default
  276.      * data model, a default column model, and a default selection
  277.      * model.
  278.      *
  279.      * @see #createDefaultDataModel
  280.      * @see #createDefaultColumnModel
  281.      * @see #createDefaultSelectionModel
  282.      */
  283.     public JTable() {
  284.         this(null, null, null);
  285.     }
  286.  
  287.     /**
  288.      * Constructs a JTable which is initialized with <i>dm</i> as the
  289.      * data model, a default column model, and a default selection
  290.      * model.
  291.      *
  292.      * @param dm        The data model for the table
  293.      * @see #createDefaultColumnModel
  294.      * @see #createDefaultSelectionModel
  295.      */
  296.     public JTable(TableModel dm) {
  297.         this(dm, null, null);
  298.     }
  299.  
  300.     /**
  301.      * Constructs a JTable which is initialized with <i>dm</i> as the
  302.      * data model, <i>cm</i> as the column model, and a default selection
  303.      * model.
  304.      *
  305.      * @param dm        The data model for the table
  306.      * @param cm        The column model for the table
  307.      * @see #createDefaultSelectionModel
  308.      */
  309.     public JTable(TableModel dm, TableColumnModel cm) {
  310.         this(dm, cm, null);
  311.     }
  312.  
  313.     /**
  314.      * Constructs a JTable which is initialized with <i>dm</i> as the
  315.      * data model, <i>cm</i> as the column model, and <i>sm</i> as the
  316.      * selection model.  If any of the parameters are <b>null</b> this
  317.      * method will initialize the table with the corresponding
  318.      * default model. The <i>autoCreateColumnsFromModel</i> flag is set
  319.      * to false if <i>cm</i> is non-null, otherwise it is set to true
  320.      * and the column model is populated with suitable TableColumns
  321.      * for the columns in <i>dm</i>.
  322.      *
  323.      * @param dm        The data model for the table
  324.      * @param cm        The column model for the table
  325.      * @param sm        The row selection model for the table
  326.      * @see #createDefaultDataModel
  327.      * @see #createDefaultColumnModel
  328.      * @see #createDefaultSelectionModel
  329.      */
  330.     public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
  331.         super();
  332.         setLayout(null);
  333.  
  334.         if (cm == null) {
  335.             cm = createDefaultColumnModel();
  336.             autoCreateColumnsFromModel = true;
  337.         }
  338.         setColumnModel(cm);
  339.  
  340.         if (sm == null)
  341.             sm = createDefaultSelectionModel();
  342.         setSelectionModel(sm);
  343.  
  344.     // Set the model last, that way if the autoCreatColumnsFromModel has
  345.     // been set above, we will automatically populate an empty columnModel
  346.     // with suitable columns for the new model.
  347.         if (dm == null)
  348.             dm = createDefaultDataModel();
  349.         setModel(dm);
  350.  
  351.         initializeLocalVars();
  352.         updateUI();
  353.     }
  354.  
  355.     /**
  356.      * Constructs a JTable with <i>numRows</i> and <i>numColumns</i> of
  357.      * empty cells using the DefaultTableModel.  The columns will have
  358.      * names of the form "A", "B", "C", etc.
  359.      *
  360.      * @param numRows           The number of rows the table holds
  361.      * @param numColumns        The number of columns the table holds
  362.      * @see javax.swing.table.DefaultTableModel
  363.      */
  364.     public JTable(int numRows, int numColumns) {
  365.         this(new DefaultTableModel(numRows, numColumns));
  366.     }
  367.  
  368.     /**
  369.      * Constructs a JTable to display the values in the Vector of Vectors,
  370.      * <i>rowData</i>, with column names, <i>columnNames</i>.
  371.      * The Vectors contained in <i>rowData</i> should contain the values
  372.      * for that row. In other words, the value of the cell at row 1,
  373.      * column 5 can be obtained with the following code:
  374.      * <p>
  375.      * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
  376.      * <p>
  377.      * All rows must be of the same length as <i>columnNames</i>.
  378.      * <p>
  379.      * @param rowData           The data for the new table
  380.      * @param columnNames       Names of each column
  381.      */
  382.     public JTable(final Vector rowData, final Vector columnNames) {
  383.         this(new AbstractTableModel() {
  384.             public String getColumnName(int column) { return columnNames.elementAt(column).toString(); }
  385.             public int getRowCount() { return rowData.size(); }
  386.             public int getColumnCount() { return columnNames.size(); }
  387.             public Object getValueAt(int row, int column) {
  388.                 return ((Vector)rowData.elementAt(row)).elementAt(column);
  389.             }
  390.             public boolean isCellEditable(int row, int column) { return true; }
  391.             public void setValueAt(Object value, int row, int column) {
  392.                 ((Vector)rowData.elementAt(row)).setElementAt(value, column);
  393.                 fireTableCellUpdated(row, column);
  394.             }
  395.         });
  396.     }
  397.  
  398.     /**
  399.      * Constructs a JTable to display the values in the two dimensional array,
  400.      * <i>rowData</i>, with column names, <i>columnNames</i>.
  401.      * <i>rowData</i> is an Array of rows, so the value of the cell at row 1,
  402.      * column 5 can be obtained with the following code:
  403.      * <p>
  404.      * <pre> rowData[1][5]; </pre>
  405.      * <p>
  406.      * All rows must be of the same length as <i>columnNames</i>.
  407.      * <p>
  408.      * @param rowData           The data for the new table
  409.      * @param columnNames       Names of each column
  410.      */
  411.     public JTable(final Object[][] rowData, final Object[] columnNames) {
  412.         this(new AbstractTableModel() {
  413.             public String getColumnName(int column) { return columnNames[column].toString(); }
  414.             public int getRowCount() { return rowData.length; }
  415.             public int getColumnCount() { return columnNames.length; }
  416.             public Object getValueAt(int row, int col) { return rowData[row][col]; }
  417.             public boolean isCellEditable(int row, int column) { return true; }
  418.             public void setValueAt(Object value, int row, int col) {
  419.                 rowData[row][col] = value;
  420.                 fireTableCellUpdated(row, col);
  421.             }
  422.         });
  423.     }
  424.  
  425.     /**
  426.      * Calls <code>configureEnclosingScrollPane</code>.
  427.      *
  428.      * @see #configureEnclosingScrollPane
  429.      */
  430.     public void addNotify() {
  431.         super.addNotify();
  432.         configureEnclosingScrollPane();
  433.     }
  434.  
  435.     /**
  436.      * If the JTable is the viewportView of an enclosing JScrollPane
  437.      * (the usual situation), configure this ScrollPane by, amongst other things,
  438.      * installing the table's tableHeader as the columnHeaderView of the scrollpane.
  439.      * When a JTable is added to a JScrollPane in the usual way,
  440.      * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
  441.      * called in the JTable (when the table is added to the viewport).
  442.      * JTable's <code>addNotify</code> method in turn calls this method
  443.      * which is protected so that this default installation procedure can
  444.      * be overridden by a subclass.
  445.      *
  446.      * @see #addNotify
  447.      */
  448.     protected void configureEnclosingScrollPane() {
  449.         Container p = getParent();
  450.         if (p instanceof JViewport) {
  451.             Container gp = p.getParent();
  452.             if (gp instanceof JScrollPane) {
  453.                 JScrollPane scrollPane = (JScrollPane)gp;
  454.                 // Make certain we are the viewPort's view and not, for
  455.                 // example, the rowHeaderView of the scrollPane -
  456.                 // an implementor of fixed columns might do this.
  457.                 JViewport viewport = scrollPane.getViewport();
  458.                 if (viewport == null || viewport.getView() != this) {
  459.                     return;
  460.                 }
  461.                 scrollPane.setColumnHeaderView(getTableHeader());
  462.                 scrollPane.getViewport().setBackingStoreEnabled(true);
  463.                 scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
  464.             }
  465.         }
  466.     }
  467.  
  468. //
  469. // Static Methods
  470. //
  471.  
  472.     /**
  473.      * Equivalent to <code>new JScrollPane(aTable)</code>.
  474.      *
  475.      * @deprecated As of Swing version 1.0.2,
  476.      * replaced by <code>new JScrollPane(aTable)</code>.
  477.      */
  478.     static public JScrollPane createScrollPaneForTable(JTable aTable) {
  479.         return new JScrollPane(aTable);
  480.     }
  481.  
  482. //
  483. // Table Attributes
  484. //
  485.  
  486.     /**
  487.      * Sets the tableHeader working with this JTable to <I>newHeader</I>.
  488.      * It is legal to have a <B>null</B> tableHeader.
  489.      *
  490.      * @param   newHeader                       new tableHeader
  491.      * @see     #getTableHeader
  492.      * @beaninfo
  493.      * description: The JTableHeader instance which renders the column headers.
  494.      */
  495.     public void setTableHeader(JTableHeader newHeader) {
  496.         if (tableHeader != newHeader) {
  497.             // Release the old header
  498.             if (tableHeader != null)
  499.                 tableHeader.setTable(null);
  500.  
  501.             tableHeader = newHeader;
  502.             if (tableHeader != null)
  503.                 tableHeader.setTable(this);
  504.         }
  505.     }
  506.  
  507.     /**
  508.      * Returns the tableHeader working with this JTable.
  509.      *
  510.      * @return  the tableHeader working with the receiver
  511.      * @see     #setTableHeader
  512.      */
  513.     public JTableHeader getTableHeader() {
  514.         return tableHeader;
  515.     }
  516.  
  517.     /**
  518.      * Sets the height for rows to <I>newRowHeight</I> and invokes tile
  519.      *
  520.      * @param   newRowHeight                    new row height
  521.      * @exception IllegalArgumentException      If <I>newRowHeight</I> is
  522.      *                                          less than 1.
  523.      * @see     #getRowHeight
  524.      * @beaninfo
  525.      * description: The height of the cells including the inter-cell spacing.
  526.      */
  527.     public void setRowHeight(int newHeight) {
  528.         if (newHeight <= 0) {
  529.             throw new IllegalArgumentException("New row height less than 1");
  530.         }
  531.         rowHeight = newHeight;
  532.  
  533.         resizeAndRepaint();
  534.     }
  535.  
  536.     /**
  537.      * Returns the height of a table row in the receiver.
  538.      * The default row height is 16.0.
  539.      *
  540.      * @return  the height of each row in the receiver
  541.      * @see     #setRowHeight
  542.      */
  543.     public int getRowHeight() {
  544.         return rowHeight;
  545.     }
  546.  
  547.     /**
  548.      * Sets the amount of emtpy space between rows.
  549.      *
  550.      * @see     #getRowMargin
  551.      */
  552.     public void setRowMargin(int rowMargin) {
  553.         this.rowMargin = rowMargin;
  554.     }
  555.  
  556.     /**
  557.      * Gets the amount of emtpy space between rows. Equivalent to:
  558.      * <code>getIntercellSpacing().height</code>.
  559.      *
  560.      * @see     #setRowMargin
  561.      */
  562.     public int getRowMargin() {
  563.         return rowMargin;
  564.     }
  565.  
  566.     /**
  567.      * Sets the width and height between cells to <I>newSpacing</I> and
  568.      * redisplays the receiver.
  569.      *
  570.      * @param   newSpacing              The new width and height intercellSpacing
  571.      * @see     #getIntercellSpacing
  572.      * @beaninfo
  573.      * description: The spacing between the cells, drawn in the background color of the JTable.
  574.      */
  575.     public void setIntercellSpacing(Dimension newSpacing) {
  576.         // Set the rowMargin here and columnMargin in the TableColumnModel
  577.         rowMargin = newSpacing.height;
  578.         getColumnModel().setColumnMargin(newSpacing.width);
  579.  
  580.         resizeAndRepaint();
  581.     }
  582.  
  583.     /**
  584.      * Returns the horizontal and vertical spacing between cells.
  585.      * The default spacing is (3, 2).
  586.      *
  587.      * @return  the horizontal and vertical spacing between cells
  588.      * @see     #setIntercellSpacing
  589.      */
  590.     public Dimension getIntercellSpacing() {
  591.         return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
  592.     }
  593.  
  594.     /**
  595.      * Sets the color used to draw grid lines to <I>color</I> and redisplays
  596.      * the receiver. The default color is gray.
  597.      *
  598.      * @param   color                           new color of the grid
  599.      * @exception IllegalArgumentException      if <I>color</I> is null
  600.      * @see     #getGridColor
  601.      */
  602.     public void setGridColor(Color newColor) {
  603.         if (newColor == null) {
  604.             throw new IllegalArgumentException("New color is null");
  605.         }
  606.         gridColor = newColor;
  607.  
  608.         // Redraw
  609.         repaint();
  610.     }
  611.  
  612.     /**
  613.      * Returns the color used to draw grid lines. The default color is gray.
  614.      *
  615.      * @return  the color used to draw grid lines
  616.      * @see     #setGridColor
  617.      */
  618.     public Color getGridColor() {
  619.         return gridColor;
  620.     }
  621.  
  622.     /**
  623.      *  Sets whether the receiver draws grid lines around cells.
  624.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  625.      *  There is no getShowGrid() method as the this state is held
  626.      *  in two variables: showHorizontalLines and showVerticalLines
  627.      *  each of which may be queried independently.
  628.      *
  629.      * @param   flag                    true if table view should draw grid lines
  630.      *
  631.      * @see     #setShowVerticalLines
  632.      * @see     #setShowHorizontalLines
  633.      * @beaninfo
  634.      * description: The color used to draw the grid lines.
  635.      */
  636.     public void setShowGrid(boolean b) {
  637.         setShowHorizontalLines(b);
  638.         setShowVerticalLines(b);
  639.  
  640.         // Redraw
  641.         repaint();
  642.     }
  643.  
  644.     /**
  645.      *  Sets whether the receiver draws horizontal lines between cells.
  646.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  647.      *
  648.      * @param   flag                    true if table view should draw horizontal lines
  649.      * @see     #getShowHorizontalLines
  650.      * @see     #setShowGrid
  651.      * @see     #setShowVerticalLines
  652.      * @beaninfo
  653.      * description: Whether horizontal lines should be drawn in between the cells.
  654.      */
  655.     public void setShowHorizontalLines(boolean b) {
  656.         showHorizontalLines = b;
  657.  
  658.         // Redraw
  659.         repaint();
  660.     }
  661.  
  662.     /**
  663.      *  Sets whether the receiver draws vertical lines between cells.
  664.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  665.      *
  666.      * @param   flag                    true if table view should draw vertical lines
  667.      * @see     #getShowVerticalLines
  668.      * @see     #setShowGrid
  669.      * @see     #setShowHorizontalLines
  670.      * @beaninfo
  671.      * description: Whether vertical lines should be drawn in between the cells.
  672.      */
  673.     public void setShowVerticalLines(boolean b) {
  674.         showVerticalLines = b;
  675.  
  676.         // Redraw
  677.         repaint();
  678.     }
  679.  
  680.     /**
  681.      * Returns true if the receiver draws horizontal lines between cells, false if it
  682.      * doesn't. The default is true.
  683.      *
  684.      * @return  true if the receiver draws horizontal lines between cells, false if it
  685.      *          doesn't
  686.      * @see     #setShowHorizontalLines
  687.      */
  688.     public boolean getShowHorizontalLines() {
  689.         return showHorizontalLines;
  690.     }
  691.  
  692.     /**
  693.      * Returns true if the receiver draws vertical lines between cells, false if it
  694.      * doesn't. The default is true.
  695.      *
  696.      * @return  true if the receiver draws vertical lines between cells, false if it
  697.      *          doesn't
  698.      * @see     #setShowVerticalLines
  699.      */
  700.     public boolean getShowVerticalLines() {
  701.         return showVerticalLines;
  702.     }
  703.  
  704.     /**
  705.      * Sets the table's auto resize mode when the table is resized.
  706.      *
  707.      * @param   mode One of 5 legal values:
  708.      *                   AUTO_RESIZE_OFF,
  709.      *                   AUTO_RESIZE_NEXT_COLUMN,
  710.      *                   AUTO_RESIZE_SUBSEQUENT_COLUMNS,
  711.      *                   AUTO_RESIZE_LAST_COLUMN,
  712.      *                   AUTO_RESIZE_ALL_COLUMNS
  713.      *
  714.      * @see     #getAutoResizeMode
  715.      * @see     #sizeColumnsToFit(int)
  716.      * @beaninfo
  717.      * description: Whether the columns should adjust themselves automatically.
  718.      *        enum: AUTO_RESIZE_OFF                JTable.AUTO_RESIZE_OFF
  719.      *              AUTO_RESIZE_NEXT_COLUMN        JTable.AUTO_RESIZE_NEXT_COLUMN
  720.      *              AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
  721.      *              AUTO_RESIZE_LAST_COLUMN        JTable.AUTO_RESIZE_LAST_COLUMN
  722.      *              AUTO_RESIZE_ALL_COLUMNS        JTable.AUTO_RESIZE_ALL_COLUMNS
  723.      */
  724.     public void setAutoResizeMode(int mode) {
  725.         if ((mode == AUTO_RESIZE_OFF) ||
  726.             (mode == AUTO_RESIZE_NEXT_COLUMN) ||
  727.             (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) ||
  728.             (mode == AUTO_RESIZE_LAST_COLUMN) ||
  729.             (mode == AUTO_RESIZE_ALL_COLUMNS)) {
  730.             autoResizeMode = mode;
  731.             resizeAndRepaint();
  732.             tableHeader.resizeAndRepaint();
  733.         }
  734.     }
  735.  
  736.     /**
  737.      * Returns auto resize mode of the table.
  738.      *
  739.      * @return  the autoResizeMode of the table
  740.      *
  741.      * @see     #setAutoResizeMode
  742.      * @see     #sizeColumnsToFit(int)
  743.      */
  744.     public int getAutoResizeMode() {
  745.         return autoResizeMode;
  746.     }
  747.  
  748.     /**
  749.      * Sets the table's autoCreateColumnsFromModel flag.  This method
  750.      * will call createDefaultColumnsFromModel() if <i>createColumns</i>
  751.      * is true.
  752.      *
  753.      * @param   createColumns   true if JTable should auto create columns
  754.      * @see     #getAutoCreateColumnsFromModel
  755.      * @see     #createDefaultColumnsFromModel
  756.      * @beaninfo
  757.      * description: Automatically populate the columnModel when a new TableModel is submitted.
  758.      */
  759.     public void setAutoCreateColumnsFromModel(boolean createColumns) {
  760.         if (autoCreateColumnsFromModel != createColumns) {
  761.             autoCreateColumnsFromModel = createColumns;
  762.  
  763.             if (autoCreateColumnsFromModel)
  764.                 createDefaultColumnsFromModel();
  765.         }
  766.     }
  767.  
  768.     /**
  769.      * Returns whether the table will create default columns from the model.
  770.      * If this is true, setModel() will clear any existing columns and
  771.      * create new columns from the new model.  Also if the event in the
  772.      * the tableChanged() notification specified the entired table changed
  773.      * then the columns will be rebuilt.  The default is true.
  774.      *
  775.      * @return  the autoCreateColumnsFromModel of the table
  776.      * @see     #setAutoCreateColumnsFromModel
  777.      * @see     #createDefaultColumnsFromModel
  778.      */
  779.     public boolean getAutoCreateColumnsFromModel() {
  780.         return autoCreateColumnsFromModel;
  781.     }
  782.  
  783.     /**
  784.      * This method will create default columns for the table from
  785.      * the data model using the getColumnCount() and getColumnClass() methods
  786.      * defined in the TableModel interface.
  787.      * <p>
  788.      * This method will clear any exsiting columns before creating the
  789.      * new columns based on information from the model.
  790.      *
  791.      * @see     #getAutoCreateColumnsFromModel
  792.      */
  793.     public void createDefaultColumnsFromModel() {
  794.         TableModel m = getModel();
  795.         if (m != null) {
  796.             // Remove any current columns
  797.             TableColumnModel cm = getColumnModel();
  798.             cm.removeColumnModelListener(this);
  799.             while (cm.getColumnCount() > 0)
  800.                 cm.removeColumn(cm.getColumn(0));
  801.  
  802.             // Create new columns from the data model info
  803.             for (int i = 0; i < m.getColumnCount(); i++) {
  804.                 TableColumn newColumn = new TableColumn(i);
  805.                 addColumn(newColumn);
  806.             }
  807.             cm.addColumnModelListener(this);
  808.         }
  809.     }
  810.  
  811.     /**
  812.      * Set a default renderer to be used if no renderer has been set in
  813.      * a TableColumn. If renderer is null, remove the default renderer 
  814.      * for this column class. 
  815.      *
  816.      * @see     #getDefaultRenderer
  817.      * @see     #setDefaultEditor
  818.      */
  819.     public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) { 
  820.     if (renderer != null) {
  821.         defaultRenderersByColumnClass.put(columnClass, renderer); 
  822.     }
  823.     else {
  824.         defaultRenderersByColumnClass.remove(columnClass); 
  825.     }
  826.     }
  827.  
  828.     /**
  829.      * Returns the renderer to be used when no renderer has been set in
  830.      * a TableColumn. During the rendering of cells the renderer is fetched from
  831.      * a Hashtable of entries according to the class of the cells in the column. If
  832.      * there is no entry for this <I>columnClass</I> the method returns
  833.      * the entry for the most specific superclass. The JTable installs entries
  834.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  835.      * or replaced.
  836.      *
  837.      * @see     #setDefaultRenderer
  838.      * @see     #getColumnClass
  839.      */
  840.     public TableCellRenderer getDefaultRenderer(Class columnClass) {
  841.         if (columnClass == null) {
  842.             return null;
  843.         }
  844.         else {
  845.             Object renderer = defaultRenderersByColumnClass.get(columnClass);
  846.             if (renderer != null) {
  847.                 return (TableCellRenderer)renderer;
  848.             }
  849.             else {
  850.                 return getDefaultRenderer(columnClass.getSuperclass());
  851.             }
  852.         }
  853.     }
  854.  
  855.     /**
  856.      * Set a default editor to be used if no editor has been set in
  857.      * a TableColumn. If no editing is required in a table, or a
  858.      * particular column in a table, use the isCellEditable()
  859.      * method in the TableModel interface to ensure that the
  860.      * JTable will not start an editor in these columns. 
  861.      * If editor is null, remove the default editor for this 
  862.      * column class. 
  863.      *
  864.      * @see     TableModel#isCellEditable
  865.      * @see     #getDefaultEditor
  866.      * @see     #setDefaultRenderer
  867.      */
  868.     public void setDefaultEditor(Class columnClass, TableCellEditor editor) {
  869.         if (editor != null) {
  870.         defaultEditorsByColumnClass.put(columnClass, editor); 
  871.     }
  872.     else {
  873.         defaultEditorsByColumnClass.remove(columnClass);        
  874.     }
  875.     }
  876.  
  877.     /**
  878.      * Returns the editor to be used when no editor has been set in
  879.      * a TableColumn. During the editing of cells the editor is fetched from
  880.      * a Hashtable of entries according to the class of the cells in the column. If
  881.      * there is no entry for this <I>columnClass</I> the method returns
  882.      * the entry for the most specific superclass. The JTable installs entries
  883.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  884.      * or replaced.
  885.      *
  886.      * @see     #setDefaultEditor
  887.      * @see     #getColumnClass
  888.      */
  889.     public TableCellEditor getDefaultEditor(Class columnClass) {
  890.         if (columnClass == null) {
  891.             return null;
  892.         }
  893.         else {
  894.             Object editor = defaultEditorsByColumnClass.get(columnClass);
  895.             if (editor != null) {
  896.                 return (TableCellEditor)editor;
  897.             }
  898.             else {
  899.                 return getDefaultEditor(columnClass.getSuperclass());
  900.             }
  901.         }
  902.     }
  903.  
  904. //
  905. // Selection methods
  906. //
  907.     /**
  908.      * Sets the table's selection mode to allow only single selections, a single
  909.      * contiguous interval, or multiple intervals.
  910.      *
  911.      * NOTE:<br>
  912.      * JTable provides all the methods for handling column and row selection.
  913.      * When setting states, such as setSelectionMode, it not only
  914.      * updates the mode for the row selection model but also sets similar
  915.      * values in the selection model of the columnModel.
  916.      * If you want to have the row and column selection models operating 
  917.      * in different modes, set them both directly. 
  918.      * <p>
  919.      * Both the row and column selection models for the JTable default
  920.      * to using a DefaultListSelectionModel so that JTable works the same
  921.      * way as the JList. See setSelectionMode() in JList for details
  922.      * about the modes.
  923.      *
  924.      * @see JList#setSelectionMode
  925.      * @beaninfo
  926.      * description: The selection mode used by the row and column selection models.
  927.      *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
  928.      *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
  929.      *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  930.      */
  931.     public void setSelectionMode(int selectionMode) {
  932.         clearSelection();
  933.         getSelectionModel().setSelectionMode(selectionMode);
  934.         getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
  935.     }
  936.  
  937.     /**
  938.      * Sets whether the rows in this model can be selected.
  939.      *
  940.      * @see #getRowSelectionAllowed
  941.      * @beaninfo
  942.      * description: If true, an entire row is selected for each selected cell.
  943.      */
  944.     public void setRowSelectionAllowed(boolean flag) {
  945.         rowSelectionAllowed = flag;
  946.     }
  947.  
  948.     /**
  949.      * Returns true if rows can be selected.
  950.      *
  951.      * @return true if rows can be selected
  952.      * @see #setRowSelectionAllowed
  953.      */
  954.     public boolean getRowSelectionAllowed() {
  955.         return rowSelectionAllowed;
  956.     }
  957.  
  958.     /**
  959.      * Sets whether the columns in this model can be selected.
  960.      *
  961.      * @see #getColumnSelectionAllowed
  962.      * @beaninfo
  963.      * description: If true, an entire column is selected for each selected cell.
  964.      */
  965.     public void setColumnSelectionAllowed(boolean flag) {
  966.         columnModel.setColumnSelectionAllowed(flag);
  967.     }
  968.  
  969.     /**
  970.      * Returns true if columns can be selected.
  971.      *
  972.      * @return true if columns can be selected.
  973.      * @see #setColumnSelectionAllowed
  974.      */
  975.     public boolean getColumnSelectionAllowed() {
  976.         return columnModel.getColumnSelectionAllowed();
  977.     }
  978.  
  979.     /**
  980.      * Sets whether this table allows both a column selection and a
  981.      * row selection to exist at the same time. When set, this results
  982.      * in a facility to select a rectangular region of cells in the display.
  983.      * This flag over-rides the row and column selection
  984.      * modes ensuring that cell selection is possible whenever this flag is set.
  985.  
  986.      * @see #getCellSelectionEnabled
  987.      * @beaninfo
  988.      * description: Select a rectangular region of cells rather than rows or columns.
  989.      */
  990.     public void setCellSelectionEnabled(boolean flag) {
  991.         cellSelectionEnabled = flag;
  992.     }
  993.  
  994.     /**
  995.      * Returns true if simultaneous row and column selections are allowed
  996.      *
  997.      * @return true if simultaneous row and column selections are allowed
  998.      * @see #setCellSelectionEnabled
  999.      */
  1000.     public boolean getCellSelectionEnabled() {
  1001.         return cellSelectionEnabled;
  1002.     }
  1003.  
  1004.     /**
  1005.      *  Select all rows, columns and cells in the table. 
  1006.      */
  1007.     public void selectAll() {
  1008.         // If I'm currently editing, then I should stop editing
  1009.         if (isEditing()) {
  1010.             removeEditor();
  1011.         }
  1012.         setRowSelectionInterval(0, getRowCount()-1);
  1013.     setColumnSelectionInterval(0, getColumnCount()-1);
  1014.     }
  1015.  
  1016.     /**
  1017.      * Deselects all selected columns and rows.
  1018.      */
  1019.     public void clearSelection() {
  1020.         columnModel.getSelectionModel().clearSelection();
  1021.         selectionModel.clearSelection();
  1022.     }
  1023.  
  1024.     /**
  1025.      * Selects the rows from <i>index0</i> to <i>index1</i> inclusive.
  1026.      *
  1027.      * @param   index0 one end of the interval.
  1028.      * @param   index1 other end of the interval
  1029.      */
  1030.     public void setRowSelectionInterval(int index0, int index1) {
  1031.         selectionModel.setSelectionInterval(index0, index1);
  1032.     }
  1033.  
  1034.     /**
  1035.      * Selects the columns from <i>index0</i> to <i>index1</i> inclusive.
  1036.      *
  1037.      * @param   index0 one end of the interval.
  1038.      * @param   index1 other end of the interval
  1039.      */
  1040.     public void setColumnSelectionInterval(int index0, int index1) {
  1041.         columnModel.getSelectionModel().setSelectionInterval(index0, index1);
  1042.     }
  1043.  
  1044.     /**
  1045.      * Adds the rows from <i>index0</i> to <i>index0</i> inclusive to
  1046.      * the current selection.
  1047.      *
  1048.      * @param   index0 one end of the interval.
  1049.      * @param   index1 other end of the interval
  1050.      */
  1051.     public void addRowSelectionInterval(int index0, int index1) {
  1052.         selectionModel.addSelectionInterval(index0, index1);
  1053.     }
  1054.  
  1055.     /**
  1056.      * Adds the columns from <i>index0</i> to <i>index0</i> inclusive to
  1057.      * the current selection.
  1058.      *
  1059.      * @param   index0 one end of the interval.
  1060.      * @param   index1 other end of the interval
  1061.      */
  1062.     public void addColumnSelectionInterval(int index0, int index1) {
  1063.         columnModel.getSelectionModel().addSelectionInterval(index0, index1);
  1064.     }
  1065.  
  1066.     /**
  1067.      * Deselects the rows from <i>index0</i> to <i>index0</i> inclusive.
  1068.      *
  1069.      * @param   index0 one end of the interval.
  1070.      * @param   index1 other end of the interval
  1071.      */
  1072.     public void removeRowSelectionInterval(int index0, int index1) {
  1073.         selectionModel.removeSelectionInterval(index0, index1);
  1074.     }
  1075.  
  1076.     /**
  1077.      * Deselects the columns from <i>index0</i> to <i>index0</i> inclusive.
  1078.      *
  1079.      * @param   index0 one end of the interval.
  1080.      * @param   index1 other end of the interval
  1081.      */
  1082.     public void removeColumnSelectionInterval(int index0, int index1) {
  1083.         columnModel.getSelectionModel().removeSelectionInterval(index0, index1);
  1084.     }
  1085.  
  1086.     /**
  1087.      * Returns the index of the last row selected or added to the selection.
  1088.      *
  1089.      * @return the index of the last row selected or added to the selection,
  1090.      *         (lead selection) or -1 if no row is selected.
  1091.      * @see #getSelectedRows
  1092.      */
  1093.     public int getSelectedRow() {
  1094.         if (selectionModel != null) {
  1095.             return selectionModel.getAnchorSelectionIndex();
  1096.         }
  1097.         return -1;
  1098.     }
  1099.  
  1100.     /**
  1101.      * Returns the index of the last column selected or added to the selection.
  1102.      *
  1103.      * @return the index of the last column selected or added to the selection,
  1104.      *         (lead selection) or -1 if no column is selected.
  1105.      * @see #getSelectedColumns
  1106.      */
  1107.     public int getSelectedColumn() {
  1108.         return columnModel.getSelectionModel().getAnchorSelectionIndex();
  1109.     }
  1110.  
  1111.     /**
  1112.      * Returns the indices of all selected rows.
  1113.      *
  1114.      * @return an array of ints containing the indices of all selected rows,
  1115.      *         or an empty array if no row is selected.
  1116.      * @see #getSelectedRow
  1117.      */
  1118.     public int[] getSelectedRows() {
  1119.         if (selectionModel != null) {
  1120.             int iMin = selectionModel.getMinSelectionIndex();
  1121.             int iMax = selectionModel.getMaxSelectionIndex();
  1122.  
  1123.             if ((iMin == -1) || (iMax == -1)) {
  1124.                 return new int[0];
  1125.             }
  1126.  
  1127.             int[] rvTmp = new int[1+ (iMax - iMin)];
  1128.             int n = 0;
  1129.             for(int i = iMin; i <= iMax; i++) {
  1130.                 if (selectionModel.isSelectedIndex(i)) {
  1131.                     rvTmp[n++] = i;
  1132.                 }
  1133.             }
  1134.             int[] rv = new int[n];
  1135.             System.arraycopy(rvTmp, 0, rv, 0, n);
  1136.             return rv;
  1137.         }
  1138.         return  new int[0];
  1139.     }
  1140.  
  1141.     /**
  1142.      * Returns the indices of all selected columns.
  1143.      *
  1144.      * @return an array of ints containing the indices of all selected columns,
  1145.      *         or an empty array if no column is selected.
  1146.      * @see #getSelectedColumn
  1147.      */
  1148.     public int[] getSelectedColumns() {
  1149.         return columnModel.getSelectedColumns();
  1150.     }
  1151.  
  1152.     /**
  1153.      * Returns the number of selected rows.
  1154.      *
  1155.      * @return the number of selected rows, 0 if no columns are selected
  1156.      */
  1157.     public int getSelectedRowCount() {
  1158.         if (selectionModel != null) {
  1159.             int iMin = selectionModel.getMinSelectionIndex();
  1160.             int iMax = selectionModel.getMaxSelectionIndex();
  1161.             int count = 0;
  1162.  
  1163.             for(int i = iMin; i <= iMax; i++) {
  1164.                 if (selectionModel.isSelectedIndex(i)) {
  1165.                     count++;
  1166.                 }
  1167.             }
  1168.             return count;
  1169.         }
  1170.         return 0;
  1171.     }
  1172.  
  1173.     /**
  1174.      * Returns the number of selected columns.
  1175.      *
  1176.      * @return the number of selected columns, 0 if no columns are selected
  1177.      */
  1178.     public int getSelectedColumnCount() {
  1179.         return columnModel.getSelectedColumnCount();
  1180.     }
  1181.  
  1182.     /**
  1183.      * Returns true if the row at the specified index is selected
  1184.      *
  1185.      * @return true if the row at index <I>row</I> is selected, where 0 is the
  1186.      *              first row
  1187.      * @exception IllegalArgumentException      if <I>row</I> is not in the
  1188.      *                                          valid range
  1189.      */
  1190.     public boolean isRowSelected(int row) {
  1191.         if (selectionModel != null)
  1192.             return selectionModel.isSelectedIndex(row);
  1193.         return false;
  1194.     }
  1195.  
  1196.     /**
  1197.      * Returns true if the column at the specified index is selected
  1198.      *
  1199.      * @return true if the column at index <I>column</I> is selected, where
  1200.      *              0 is the first column
  1201.      * @exception IllegalArgumentException      if <I>column</I> is not in the
  1202.      *                                          valid range
  1203.      */
  1204.     public boolean isColumnSelected(int column) {
  1205.         return columnModel.getSelectionModel().isSelectedIndex(column);
  1206.     }
  1207.  
  1208.     /**
  1209.      * Returns true if the cell at the specified position is selected.
  1210.      *
  1211.      * @return true if the cell at index <I>(row, column)</I> is selected,
  1212.      *              where the first row and first column are at index 0
  1213.      * @exception IllegalArgumentException      if <I>row</I> or <I>column</I>
  1214.      *                                          are not in the valid range
  1215.      */
  1216.     public boolean isCellSelected(int row, int column) {
  1217.         if (cellSelectionEnabled)
  1218.             return isRowSelected(row) && isColumnSelected(column);
  1219.         else
  1220.             return (getRowSelectionAllowed() && isRowSelected(row)) ||
  1221.                    (getColumnSelectionAllowed() && isColumnSelected(column));
  1222.     }
  1223.  
  1224.     /**
  1225.      * Returns the foreground color for selected cells.
  1226.      *
  1227.      * @return the Color object for the foreground property
  1228.      * @see #setSelectionForeground
  1229.      * @see #setSelectionBackground
  1230.      */
  1231.     public Color getSelectionForeground() {
  1232.         return selectionForeground;
  1233.     }
  1234.  
  1235.     /**
  1236.      * Set the foreground color for selected cells.  Cell renderers
  1237.      * can use this color to render text and graphics for selected
  1238.      * cells.
  1239.      * <p>
  1240.      * The default value of this property is defined by the look
  1241.      * and feel implementation.
  1242.      * <p>
  1243.      * This is a JavaBeans bound property.
  1244.      *
  1245.      * @param selectionForeground  the Color to use in the foreground
  1246.      *                             for selected list items
  1247.      * @see #getSelectionForeground
  1248.      * @see #setSelectionBackground
  1249.      * @see #setForeground
  1250.      * @see #setBackground
  1251.      * @see #setFont
  1252.      * @beaninfo
  1253.      *       bound: true
  1254.      * description: A default foreground color for selected cells.
  1255.      */
  1256.     public void setSelectionForeground(Color selectionForeground) {
  1257.         Color oldValue = this.selectionForeground;
  1258.         this.selectionForeground = selectionForeground;
  1259.         firePropertyChange("selectionForeground", oldValue, selectionForeground);
  1260.     }
  1261.  
  1262.     /**
  1263.      * Returns the background color for selected cells.
  1264.      *
  1265.      * @return the Color used for the background of selected list items
  1266.      * @see #setSelectionBackground
  1267.      * @see #setSelectionForeground
  1268.      */
  1269.     public Color getSelectionBackground() {
  1270.         return selectionBackground;
  1271.     }
  1272.  
  1273.     /**
  1274.      * Set the background color for selected cells.  Cell renderers
  1275.      * can use this color to the fill selected cells.
  1276.      * <p>
  1277.      * The default value of this property is defined by the look
  1278.      * and feel implementation.
  1279.      * <p>
  1280.      * This is a JavaBeans bound property.
  1281.      *
  1282.      * @param selectionBackground  the Color to use for the background
  1283.      *                             of selected cells
  1284.      * @see #getSelectionBackground
  1285.      * @see #setSelectionForeground
  1286.      * @see #setForeground
  1287.      * @see #setBackground
  1288.      * @see #setFont
  1289.      * @beaninfo
  1290.      *       bound: true
  1291.      * description: A default background color for selected cells.
  1292.      */
  1293.     public void setSelectionBackground(Color selectionBackground) {
  1294.         Color oldValue = this.selectionBackground;
  1295.         this.selectionBackground = selectionBackground;
  1296.         firePropertyChange("selectionBackground", oldValue, selectionBackground);
  1297.     }
  1298.  
  1299.     /**
  1300.      * Returns the <B>TableColumn</B> object for the column in the table
  1301.      * whose identifier is equal to <I>identifier</I>, when compared using
  1302.      * <I>equals()</I>.
  1303.      *
  1304.      * @return  the TableColumn object with matching identifier
  1305.      * @exception IllegalArgumentException      if <I>identifier</I> is null or no TableColumn has this identifier
  1306.      *
  1307.      * @param   identifier                      the identifier object
  1308.      */
  1309.     public TableColumn getColumn(Object identifier) {
  1310.         TableColumnModel cm = getColumnModel();
  1311.         int columnIndex = cm.getColumnIndex(identifier);
  1312.         return cm.getColumn(columnIndex);
  1313.     }
  1314.  
  1315. //
  1316. // Informally implement the TableModel interface.
  1317. //
  1318.  
  1319.     /**
  1320.      * Return the index of the column in the model whose data is being displayed in
  1321.      * the column <I>viewColumnIndex</I> in the display. Returns <I>viewColumnIndex</I>
  1322.      * unchanged when <I>viewColumnIndex</I> is less than zero.
  1323.      *
  1324.      * @see #convertColumnIndexToView
  1325.      */
  1326.     public int convertColumnIndexToModel(int viewColumnIndex) {
  1327.         if (viewColumnIndex < 0) {
  1328.             return viewColumnIndex;
  1329.         }
  1330.         return getColumnModel().getColumn(viewColumnIndex).getModelIndex();
  1331.     }
  1332.  
  1333.     /**
  1334.      * Return the index of the column in the view which is displaying the
  1335.      * data from the column <I>modelColumnIndex</I> in the model. Returns
  1336.      * -1 if this column is not being displayed. Returns <I>modelColumnIndex</I>
  1337.      * unchanged when <I>modelColumnIndex</I> is less than zero.
  1338.      *
  1339.      * @see #convertColumnIndexToModel
  1340.      */
  1341.     public int convertColumnIndexToView(int modelColumnIndex) {
  1342.         if (modelColumnIndex < 0) {
  1343.             return modelColumnIndex;
  1344.         }
  1345.         TableColumnModel cm = getColumnModel();
  1346.         for (int column = 0; column < getColumnCount(); column++) {
  1347.             if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
  1348.                 return column;
  1349.             }
  1350.         }
  1351.         return -1;
  1352.     }
  1353.  
  1354.     /**
  1355.      * Returns the number of rows in the table.
  1356.      *
  1357.      * @see #getColumnCount
  1358.      */
  1359.     public int getRowCount() {
  1360.         return getModel().getRowCount();
  1361.     }
  1362.  
  1363.     /**
  1364.      * Returns the number of columns in the column model, note this may
  1365.      * be different to the number of columns in the table model.
  1366.      *
  1367.      * @return  the number of columns in the table
  1368.      * @see #getRowCount
  1369.      */
  1370.     public int getColumnCount() {
  1371.         return getColumnModel().getColumnCount();
  1372.     }
  1373.  
  1374.     /**
  1375.      * Returns the name of the column at the specified view position.
  1376.      *
  1377.      * @return the name of the column at position <I>column</I> in the view
  1378.      *         where the first column is column 0.
  1379.      */
  1380.     public String getColumnName(int column) {
  1381.         return getModel().getColumnName(convertColumnIndexToModel(column));
  1382.     }
  1383.  
  1384.     /**
  1385.      * Returns the type of the column at the specified view position.
  1386.      *
  1387.      * @return the type of the column at position <I>column</I> in the view
  1388.      *         where the first column is column 0.
  1389.      */
  1390.     public Class getColumnClass(int column) {
  1391.         return getModel().getColumnClass(convertColumnIndexToModel(column));
  1392.     }
  1393.  
  1394.     /**
  1395.      * Returns the cell value at <I>row</I> and <I>column</I>.
  1396.      * <p>
  1397.      * <b>NOTE</b>: The column is specified in the table view's display
  1398.      *              order, and not in the TableModel's column order.  This is
  1399.      *              an important distinction because as the user rearranges
  1400.      *              the columns in the table, what is at column 2 changes.
  1401.      *              Meanwhile the user's actions never affect the model's
  1402.      *              column ordering.
  1403.      *
  1404.      * @param   row             the row whose value is to be looked up
  1405.      * @param   column          the column whose value is to be looked up
  1406.      * @return  the Object at the specified cell
  1407.      */
  1408.     public Object getValueAt(int row, int column) {
  1409.         return getModel().getValueAt(row, convertColumnIndexToModel(column));
  1410.     }
  1411.  
  1412.     /**
  1413.      * Sets the value for the cell at <I>row</I> and <I>column</I>.
  1414.      * <I>aValue</I> is the new value.
  1415.      *
  1416.      * @param   aValue          the new value
  1417.      * @param   row             the row whose value is to be changed
  1418.      * @param   column          the column whose value is to be changed
  1419.      * @see #getValueAt
  1420.      */
  1421.     public void setValueAt(Object aValue, int row, int column) {
  1422.         getModel().setValueAt(aValue, row, convertColumnIndexToModel(column));
  1423.     }
  1424.  
  1425.     /**
  1426.      * Returns true if the cell at <I>row</I> and <I>column</I>
  1427.      * is editable.  Otherwise, setValueAt() on the cell will not change
  1428.      * the value of that cell.
  1429.      *
  1430.      * @param   row      the row whose value is to be looked up
  1431.      * @param   column   the column whose value is to be looked up
  1432.      * @return  true if the cell is editable.
  1433.      * @see #setValueAt
  1434.      */
  1435.     public boolean isCellEditable(int row, int column) {
  1436.         return getModel().isCellEditable(row, convertColumnIndexToModel(column));
  1437.     }
  1438. //
  1439. // Adding and removing columns in the view
  1440. //
  1441.  
  1442.     /**
  1443.      *  Appends <I>aColumn</I> to the end of the array of columns held by
  1444.      *  the JTable's column model.
  1445.      *  If the header value of <I>aColumn</I> is <I>null</I>,
  1446.      *  sets the header value of <I>aColumn</I> to the name
  1447.      *  returned by <code>getModel().getColumnName()</code>.
  1448.      *  <p>
  1449.      *  To add a column to the JTable to display the <I>modelColumn</I>'th column of
  1450.      *  data in the model, with a given <I>width</I>,
  1451.      *  <I>cellRenderer</I> and <I>cellEditor</I> you can use:
  1452.      *  <pre>
  1453.      *
  1454.      *      addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor));
  1455.      *
  1456.      *  </pre>
  1457.      *  [All of the other constructors in the TableColumn can be used in place of
  1458.      *  this one.] The model column is stored inside the TableColumn and is used during
  1459.      *  rendering and editing to locate the appropriate data values in the
  1460.      *  model. The model column does not change when columns are reordered
  1461.      *  in the view.
  1462.      *
  1463.      *  @param  aColumn         The <B>TableColumn</B> to be added
  1464.      *  @see    #removeColumn
  1465.      */
  1466.     public void addColumn(TableColumn aColumn) {
  1467.         int modelColumn = aColumn.getModelIndex();
  1468.         String columnName = getModel().getColumnName(modelColumn);
  1469.         if (aColumn.getHeaderValue() == null) {
  1470.             aColumn.setHeaderValue(columnName);
  1471.         }
  1472.         getColumnModel().addColumn(aColumn);
  1473.     }
  1474.  
  1475.     /**
  1476.      *  Removes <I>aColumn</I> from the JTable's array of columns.
  1477.      *  Note: this method does not remove the column of data from the
  1478.      *  model it just removes the TableColumn that was displaying it.
  1479.      *
  1480.      *  @param  aColumn         The <B>TableColumn</B> to be removed
  1481.      *  @see    #addColumn
  1482.      */
  1483.     public void removeColumn(TableColumn aColumn) {
  1484.         getColumnModel().removeColumn(aColumn);
  1485.     }
  1486.  
  1487.     /**
  1488.      * Moves the column <I>column</I> to the position currently occupied by the
  1489.      * column <I>targetColumn</I>.  The old column at <I>targetColumn</I> is
  1490.      * shifted left or right to make room.
  1491.      *
  1492.      * @param   column                  the index of column to be moved
  1493.      * @param   targetColumn            the new index of the column
  1494.      */
  1495.     public void moveColumn(int column, int targetColumn) {
  1496.         getColumnModel().moveColumn(column, targetColumn);
  1497.     }
  1498.  
  1499. //
  1500. // Cover methods for various models and helper methods
  1501. //
  1502.  
  1503.     /**
  1504.      * Returns the index of the column that <I>point</I> lies in, or -1 if it
  1505.      * lies outside the receiver's bounds.
  1506.      *
  1507.      * @return  the index of the column that <I>point</I> lies in, or -1 if it
  1508.      *          lies outside the receiver's bounds
  1509.      * @see     #rowAtPoint
  1510.      */
  1511.     public int columnAtPoint(Point point) {
  1512.         return getColumnModel().getColumnIndexAtX(point.x);
  1513.     }
  1514.  
  1515.     /**
  1516.      * Returns the index of the row that <I>point</I> lies in, or -1 if is
  1517.      * not in the range [0, getRowCount()-1].
  1518.      *
  1519.      * @return  the index of the row that <I>point</I> lies in, or -1 if it
  1520.      *          is not in the range [0, getRowCount()-1]
  1521.      * @see     #columnAtPoint
  1522.      */
  1523.     public int rowAtPoint(Point point) {
  1524.         int y = point.y;
  1525.  
  1526.  //       if (y < 0 || y >= getBounds().height) {
  1527.  //           return -1;
  1528.  //       }
  1529.  
  1530.         int rowHeight = getRowHeight();
  1531.         int rowSpacing = getIntercellSpacing().height;
  1532.         int totalRowHeight = rowHeight + rowSpacing;
  1533.         int result = y/totalRowHeight;
  1534.         if (result < 0) {
  1535.             return -1;
  1536.         }
  1537.         else if (result >= getRowCount()) {
  1538.             return -1;
  1539.         }
  1540.         else {
  1541.             return result;
  1542.         }
  1543.     }
  1544.  
  1545.     /**
  1546.      * Returns a rectangle locating the cell that lies at the intersection of
  1547.      * <I>row</I> and <I>column</I>.   If <I>includeSpacing</I> is true then
  1548.      * the value returned includes the intercellSpacing margin.  If it is false,
  1549.      * then the returned rect is inset by half of intercellSpacing.
  1550.      * (This is the true frame of the cell)
  1551.      *
  1552.      * @param   row                             the row to compute
  1553.      * @param   column                          the column to compute
  1554.      * @param   includeSpacing                  if true, the rect returned will
  1555.      *                                          include the correct
  1556.      *                                          intercellSpacing
  1557.      * @return  the rectangle containing the cell at index
  1558.      *          <I>row</I>,<I>column</I>
  1559.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1560.      *                                          are not in the valid range.
  1561.      */
  1562.     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
  1563.         int index = 0;
  1564.         Rectangle cellFrame;
  1565.         int columnMargin = getColumnModel().getColumnMargin();
  1566.         Enumeration enumeration = getColumnModel().getColumns();
  1567.         TableColumn aColumn;
  1568.  
  1569.         cellFrame = new Rectangle();
  1570.         cellFrame.height = getRowHeight() + rowMargin;
  1571.         cellFrame.y = row * cellFrame.height;
  1572.  
  1573.         while (enumeration.hasMoreElements()) {
  1574.             aColumn = (TableColumn)enumeration.nextElement();
  1575.             cellFrame.width = aColumn.getWidth() + columnMargin;
  1576.  
  1577.             if (index == column)
  1578.                 break;
  1579.  
  1580.             cellFrame.x += cellFrame.width;
  1581.             index++;
  1582.         }
  1583.  
  1584.         if (!includeSpacing) {
  1585.             Dimension spacing = getIntercellSpacing();
  1586.             // This is not the same as grow(), it rounds differently.
  1587.             cellFrame.setBounds(cellFrame.x +      spacing.width/2,
  1588.                                 cellFrame.y +      spacing.height/2,
  1589.                                 cellFrame.width -  spacing.width,
  1590.                                 cellFrame.height - spacing.height);
  1591.         }
  1592.         return cellFrame;
  1593.     }
  1594.  
  1595.     /**
  1596.      * Calls super.reshape(), and is overridden simply to detect changes in 
  1597.      * our bounds. After reshaping we resize the columns (similar to triggering 
  1598.      * a layout) to fit the new bounds for the component using sizeColumnsToFit(). 
  1599.      *
  1600.      * @see #sizeColumnsToFit(int)
  1601.      */
  1602.     public void reshape(int x, int y, int width, int height) {
  1603.     boolean widthChanged = (getWidth() != width); 
  1604.         super.reshape(x, y, width, height);
  1605.         if (widthChanged) {
  1606.         sizeColumnsToFit(-1);
  1607.     }
  1608.     }
  1609.  
  1610.  
  1611.     /**
  1612.      * Sizes the table columns to fit the available space.
  1613.      * @deprecated As of Swing version 1.0.3,
  1614.      * replaced by <code>sizeColumnsToFit(int)</code>.
  1615.      * @see #sizeColumnsToFit(int)
  1616.      */
  1617.     public void sizeColumnsToFit(boolean lastColumnOnly) {
  1618.         int oldAutoResizeMode = autoResizeMode;
  1619.         setAutoResizeMode(lastColumnOnly ? AUTO_RESIZE_LAST_COLUMN
  1620.                                          : AUTO_RESIZE_ALL_COLUMNS);
  1621.         sizeColumnsToFit(-1);
  1622.         setAutoResizeMode(oldAutoResizeMode);
  1623.     }
  1624.  
  1625.     /**
  1626.      *       This method will resize one or more ot the columns in the table
  1627.      *       so that the total width of all of the JTable's columns will be
  1628.      *       equal to the width of the table. 
  1629.      * <p>
  1630.      *       When setBounds() is called on the JTable, often as 
  1631.      *       a result of resizing of an enclosing window -
  1632.      *       this method is called with <code>resizingColumn</code>
  1633.      *       set to -1. This means that resizing has taken place 'outside' the
  1634.      *       JTable and the change - or 'delta' - should be distributed to all
  1635.      *       of the columns regardless of the JTable's autoResizeMode mode.
  1636.      * <p>
  1637.      *       If the <code>resizingColumn</code> is not -1, it is one of 
  1638.      *       the columns in the table that has changed size rather than 
  1639.      *       the table itself. In this case the auto-resize modes govern 
  1640.      *       the way the extra (or defecit) space is distributed 
  1641.      *       amongst the availible columns. 
  1642.      * <p>
  1643.      *       The modes are:
  1644.      * <ul>
  1645.      * <li>  AUTO_RESIZE_OFF Don't automatically adjust the column's
  1646.      *       widths at all. Use a horizontal scrollbar to accomodate the
  1647.      *       columns when their sum exceeds the width of the Viewport.
  1648.      *       If the JTable is not enclosed in a JScrollPane this may 
  1649.      *       leave parts of the table invisible.
  1650.      * <li>  AUTO_RESIZE_NEXT_COLUMN: Use just the column after the
  1651.      *       resizing column. This results in the 'boundry' or divider
  1652.      *       between adjacent cells being independently adjustable.
  1653.      * <li>  AUTO_RESIZE_SUBSEQUENT_COLUMNS: Use all columns after the
  1654.      *       one being adjusted to absorb the changes.
  1655.      * <li>  AUTO_RESIZE_LAST_COLUMN Only ever automatically adjust the
  1656.      *       size of the last column. If the bounds of the last column
  1657.      *       prevent the desired size from being allocated, set the
  1658.      *       width of the last column to the appropriate limit and make
  1659.      *       no further adjustments.
  1660.      * <li>  AUTO_RESIZE_ALL_COLUMNS Spread the delta amongst all the columns
  1661.      *       in the JTable, including the one that is being adjusted.
  1662.      * </ul>
  1663.      * <p>
  1664.      * Note: When the JTable makes adjustments to the widths of the
  1665.      *   columns it respects their minimum and maximum values absolutely.
  1666.      *   It is therefore possible that, even after this method is called,
  1667.      *   the total width of the columns is still not equal to the width
  1668.      *   of the table. When this happens the JTable does not put itself
  1669.      *   in AUTO_RESIZE_OFF mode to bring up a ScrollBar, or break other
  1670.      *   commitments of its current auto-resize mode - instead it
  1671.      *   allows its bounds to be set larger (or smaller) than the total of the
  1672.      *   column minima or maxima, meaning, either that there
  1673.      *   will not be enough room to display all of the columns, or that the
  1674.      *   columns will not fill the JTable's bounds. These respectively, result
  1675.      *   in the clipping of some columns or an area being painted in the
  1676.      *   JTable's background color during painting.
  1677.      * <p>
  1678.      *   The mechanism for distributing the delta amongst the availible 
  1679.      *   columns is provided in a private method in the JTable class: 
  1680.      * <pre>
  1681.      *   adjustSizes(long targetSize, final Resizable3 r, boolean inverse)
  1682.      * </pre>
  1683.      *   an explanation of which is provided below. Resizable3 is a private 
  1684.      *   interface that allows any data structure containing a collection 
  1685.      *   of elements with a size, preferredSize, maximumSize and minimumSize 
  1686.      *   to have its elements manipulated by the algorithm. 
  1687.      * <p>
  1688.      * <H3> Distributing the delta </H3>
  1689.      * <p>
  1690.      * <H4> Overview </H4>
  1691.      * <P>
  1692.      * Call 'DELTA' the difference between the targetSize and the 
  1693.      * sum of the preferred sizes of the elements in r. The individual 
  1694.      * sizes are calculated by taking the original preferred 
  1695.      * sizes and adding a share of the DELTA - that share being based on 
  1696.      * how far each preferred size is from its limiting bound (minimum or 
  1697.      * maximum).
  1698.      * <p>
  1699.      * <H4>Definition</H4>
  1700.      * <P>
  1701.      * Call the individual constraints min[i], max[i] and pref[i].†
  1702.      * <p>
  1703.      * Call their respective sums: MIN, MAX and PREF.†
  1704.      * <p>
  1705.      * Each new size will be calculated using: 
  1706.      * <p>
  1707.      * <pre>
  1708.      *          size[i] = pref[i] + delta[i]
  1709.      * </pre>
  1710.      * where each individual delta[i] is calculated according to: 
  1711.      * <p>
  1712.      * If (DELTA < 0) we are in shrink mode where:†
  1713.      * <p>
  1714.      * <PRE>
  1715.      * â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€  DELTA
  1716.      * â€ â€ â€ â€ â€ â€ â€  delta[i] =†††† ------------ * (pref[i] - min[i])
  1717.      * â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€  (PREF - MIN)
  1718.      * </PRE>
  1719.      * If (DELTA > 0) we are in expand mode where:†
  1720.      * <p>
  1721.      * <PRE>
  1722.      * â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€  DELTA
  1723.      * â€ â€ â€ â€ â€ â€ â€  delta[i] =†††† ------------ * (max[i] - pref[i])
  1724.      * â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€ â€  (MAX - PREF)
  1725.      * </PRE>
  1726.      * <P>
  1727.      * The overall effect is that the total size moves that same percentage, 
  1728.      * k, towards the total minimum or maximum and that percentage guarentees 
  1729.      * accomodation of the required space, DELTA.
  1730.      *
  1731.      * <H4>Details</H4>
  1732.      * <P>
  1733.      * Naive evaluation of the formulae presented here would be subject to 
  1734.      * the aggregated rounding errors caused by doing this operation in finite 
  1735.      * precision (using ints). To deal with this, the muliplying factor above, 
  1736.      * is constantly recalculated and this takes account of the rounding errors in
  1737.      * the previous iterations. The result is an algorithm which produces 
  1738.      * a set of integers whose values exactly sum to the supplied 
  1739.      * <code>targetSize</code>, and does so by spreading the rounding 
  1740.      * errors evenly over the given elements.
  1741.      *
  1742.      * <H4>When the MAX and MIN bounds are hit</H4>
  1743.      * <P>
  1744.      * When <code>targetSize</code> is outside the [MIN, MAX] range, the algorithm 
  1745.      * sets all sizes to either their appropriate limiting value (maximum or minimum).
  1746.      *
  1747.      * @param resizingColumn    The column whose resizing made this adjustment
  1748.      *                          necessary or -1 if there is no such column.
  1749.      * @see TableColumn#setWidth
  1750.      */
  1751.     public void sizeColumnsToFit(int resizingColumn) { 
  1752.         if (resizingColumn == -1) {
  1753.             setWidthsFromPreferredWidths(false); 
  1754.     }
  1755.     else { 
  1756.         if (autoResizeMode == AUTO_RESIZE_OFF) {
  1757.             Enumeration enumeration = getColumnModel().getColumns();
  1758.         while (enumeration.hasMoreElements()) {
  1759.             TableColumn aColumn = (TableColumn)enumeration.nextElement();
  1760.             aColumn.setPreferredWidth(aColumn.getWidth()); 
  1761.         }
  1762.         } 
  1763.         else {
  1764.                 int delta = getWidth() - getColumnModel().getTotalColumnWidth(); 
  1765.             accommodateDelta(resizingColumn, delta);         
  1766.         }
  1767.     }
  1768.     }
  1769.  
  1770.     private void setWidthsFromPreferredWidths(final boolean inverse) {
  1771.         int columnCount = getColumnCount(); 
  1772.     int totalIntercellSpacing = columnCount * getColumnModel().getColumnMargin(); 
  1773.         int totalWidth     = getWidth()               - totalIntercellSpacing; 
  1774.     int totalPreferred = getPreferredSize().width - totalIntercellSpacing; 
  1775.     int target = !inverse ? totalWidth : totalPreferred; 
  1776.  
  1777.     final TableColumnModel cm = columnModel; 
  1778.     Resizable3 r = new Resizable3() { 
  1779.         public int  getElementCount()      { return cm.getColumnCount(); }
  1780.         public int  getLowerBoundAt(int i) { return cm.getColumn(i).getMinWidth(); } 
  1781.         public int  getUpperBoundAt(int i) { return cm.getColumn(i).getMaxWidth(); }
  1782.         public int  getMidPointAt(int i)  { 
  1783.             if (!inverse) {
  1784.             return cm.getColumn(i).getPreferredWidth();
  1785.             }
  1786.             else {
  1787.             return cm.getColumn(i).getWidth(); 
  1788.             }
  1789.         }
  1790.         public void setSizeAt(int s, int i) { 
  1791.             if (!inverse) {
  1792.             cm.getColumn(i).setWidth(s);
  1793.             }
  1794.             else {
  1795.             cm.getColumn(i).setPreferredWidth(s); 
  1796.             }
  1797.         }
  1798.     };
  1799.  
  1800.     adjustSizes(target, r, inverse); 
  1801.     }
  1802.  
  1803.  
  1804.     // Distribute delta over columns, as indicated by the autoresize mode.  
  1805.     private void accommodateDelta(int resizingColumnIndex, int delta) { 
  1806.         int columnCount = getColumnCount();
  1807.         int from = resizingColumnIndex;
  1808.         int to = columnCount;
  1809.  
  1810.     // Use the mode to determine how to absorb the changes.
  1811.     switch(autoResizeMode) {
  1812.         case AUTO_RESIZE_NEXT_COLUMN:        from = from + 1; to = from + 1; break;
  1813.         case AUTO_RESIZE_SUBSEQUENT_COLUMNS: from = from + 1; to = columnCount; break;
  1814.         case AUTO_RESIZE_LAST_COLUMN:        from = columnCount - 1; to = from + 1; break;
  1815.         case AUTO_RESIZE_ALL_COLUMNS:        from = 0; to = columnCount; break;
  1816.         default:                             return;
  1817.     }
  1818.  
  1819.     final int start = from; 
  1820.     final int end = to; 
  1821.     final TableColumnModel cm = columnModel; 
  1822.     Resizable3 r = new Resizable3() { 
  1823.         public int  getElementCount()       { return end-start; }
  1824.         public int  getLowerBoundAt(int i)  { return cm.getColumn(i+start).getMinWidth(); } 
  1825.         public int  getUpperBoundAt(int i)  { return cm.getColumn(i+start).getMaxWidth(); }
  1826.         public int  getMidPointAt(int i)    { return cm.getColumn(i+start).getWidth(); }
  1827.         public void setSizeAt(int s, int i) {        cm.getColumn(i+start).setWidth(s); }
  1828.     };
  1829.  
  1830.     int totalWidth = 0; 
  1831.         for(int i = from; i < to; i++) {
  1832.             TableColumn aColumn = columnModel.getColumn(i);
  1833.             int input = aColumn.getWidth(); 
  1834.         totalWidth = totalWidth + input; 
  1835.         }
  1836.  
  1837.         adjustSizes(totalWidth + delta, r, false);
  1838.     
  1839.     setWidthsFromPreferredWidths(true); 
  1840.     // setWidthsFromPreferredWidths(false); 
  1841.     return; 
  1842.     }
  1843.  
  1844.     private interface Resizable2 {
  1845.         public int  getElementCount(); 
  1846.         public int  getLowerBoundAt(int i); 
  1847.         public int  getUpperBoundAt(int i);
  1848.         public void setSizeAt(int newSize, int i); 
  1849.     }
  1850.  
  1851.     private interface Resizable3 extends Resizable2 {
  1852.         public int  getMidPointAt(int i); 
  1853.     }
  1854.  
  1855.  
  1856.     private void adjustSizes(long target, final Resizable3 r, boolean inverse) { 
  1857.     int N = r.getElementCount(); 
  1858.     long totalPreferred = 0; 
  1859.     for(int i = 0; i < N; i++) { 
  1860.         totalPreferred += r.getMidPointAt(i); 
  1861.     }
  1862.     Resizable2 s; 
  1863.         if ((target < totalPreferred) == !inverse) { 
  1864.         s = new Resizable2() { 
  1865.             public int  getElementCount()      { return r.getElementCount(); }
  1866.             public int  getLowerBoundAt(int i) { return r.getLowerBoundAt(i); } 
  1867.             public int  getUpperBoundAt(int i) { return r.getMidPointAt(i); }
  1868.             public void setSizeAt(int newSize, int i) { r.setSizeAt(newSize, i); } 
  1869.  
  1870.         };
  1871.     }
  1872.     else {         
  1873.         s = new Resizable2() { 
  1874.             public int  getElementCount()      { return r.getElementCount(); }
  1875.             public int  getLowerBoundAt(int i) { return r.getMidPointAt(i); } 
  1876.             public int  getUpperBoundAt(int i) { return r.getUpperBoundAt(i); }
  1877.             public void setSizeAt(int newSize, int i) { r.setSizeAt(newSize, i); } 
  1878.  
  1879.         };
  1880.     }
  1881.     adjustSizes(target, s, !inverse); 
  1882.     }
  1883.  
  1884.     private void adjustSizes(long target, Resizable2 r, boolean limitToRange) { 
  1885.     long totalLowerBound = 0; 
  1886.     long totalUpperBound = 0; 
  1887.     for(int i = 0; i < r.getElementCount(); i++) { 
  1888.         totalLowerBound += r.getLowerBoundAt(i); 
  1889.         totalUpperBound += r.getUpperBoundAt(i); 
  1890.     }
  1891.  
  1892.     if (limitToRange) {
  1893.         target = Math.min(Math.max(totalLowerBound, target), totalUpperBound);
  1894.     }
  1895.  
  1896.     for(int i = 0; i < r.getElementCount(); i++) { 
  1897.         int lowerBound = r.getLowerBoundAt(i); 
  1898.         int upperBound = r.getUpperBoundAt(i); 
  1899.         // Check for zero. This happens when the distribution of the delta  
  1900.         // finishes early due to a series of 'fixed' entries at the end. 
  1901.         // In this case, lowerBound == upperBound, for all subsequent terms. 
  1902.         int newSize; 
  1903.         if (totalLowerBound == totalUpperBound) {
  1904.             newSize = lowerBound; 
  1905.         } 
  1906.         else { 
  1907.             double f = (double)(target - totalLowerBound)/(totalUpperBound - totalLowerBound); 
  1908.         newSize = (int)Math.round(lowerBound+f*(upperBound - lowerBound)); 
  1909.         // We'd need to round manually in an all integer version. 
  1910.             // size[i] = (int)(((totalUpperBound - target) * lowerBound + 
  1911.         //     (target - totalLowerBound) * upperBound)/(totalUpperBound-totalLowerBound)); 
  1912.         } 
  1913.         r.setSizeAt(newSize, i); 
  1914.         target -= newSize;
  1915.         totalLowerBound -= lowerBound;
  1916.         totalUpperBound -= upperBound;
  1917.     }
  1918.     }
  1919.  
  1920.     /**
  1921.      * Overrides JComponent's setToolTipText method to allow use of the
  1922.      * renderer's tips (if the renderer has text set).
  1923.      * <p>
  1924.      * NOTE: For JTable to properly display tooltips of its renderers
  1925.      *       JTable must be a registered component with the ToolTipManager.
  1926.      *       This is done automatically in initializeLocalVars(), but
  1927.      *       if at a later point JTable is told setToolTipText(null)
  1928.      *       it will unregister the table component, and no tips from
  1929.      *       renderers will display anymore.
  1930.      *
  1931.      * @see JComponent#getToolTipText
  1932.      */
  1933.     public String getToolTipText(MouseEvent event) {
  1934.         String tip = null;
  1935.         Point p = event.getPoint();
  1936.  
  1937.         // Locate the renderer under the event location
  1938.         int hitColumnIndex = columnAtPoint(p);
  1939.         int hitRowIndex = rowAtPoint(p);
  1940.  
  1941.         if ((hitColumnIndex != -1) && (hitRowIndex != -1)) {
  1942.             TableCellRenderer renderer = getCellRenderer(hitRowIndex, hitColumnIndex);
  1943.             Component component = prepareRenderer(renderer, hitRowIndex, hitColumnIndex);
  1944.  
  1945.             // Now have to see if the component is a JComponent before
  1946.             // getting the tip
  1947.             if (component instanceof JComponent) {
  1948.                 // Convert the event to the renderer's coordinate system
  1949.                 Rectangle cellRect = getCellRect(hitRowIndex, hitColumnIndex, false);
  1950.                 p.translate(-cellRect.x, -cellRect.y);
  1951.                 MouseEvent newEvent = new MouseEvent(component, event.getID(),
  1952.                                           event.getWhen(), event.getModifiers(),
  1953.                                           p.x, p.y, event.getClickCount(),
  1954.                                           event.isPopupTrigger());
  1955.  
  1956.                 tip = ((JComponent)component).getToolTipText(newEvent);
  1957.             }
  1958.         }
  1959.  
  1960.         // No tip from the renderer get our own tip
  1961.         if (tip == null)
  1962.             tip = getToolTipText();
  1963.  
  1964.         return tip;
  1965.     }
  1966.  
  1967. //
  1968. // Editing Support
  1969. //
  1970.  
  1971.     /**
  1972.      * Programmatically starts editing the cell at <I>row</I> and
  1973.      * <I>column</I>, if the cell is editable.
  1974.      *
  1975.      * @param   row                             the row to be edited
  1976.      * @param   column                          the column to be edited
  1977.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1978.      *                                          are not in the valid range
  1979.      * @return  false if for any reason the cell cannot be edited.
  1980.      */
  1981.     public boolean editCellAt(int row, int column) {
  1982.         return editCellAt(row, column, null);
  1983.     }
  1984.  
  1985.     /**
  1986.      * Programmatically starts editing the cell at <I>row</I> and
  1987.      * <I>column</I>, if the cell is editable.
  1988.      * To prevent the JTable from editing a particular table, column or
  1989.      * cell value, return false from the isCellEditable() method in the
  1990.      * TableModel interface.
  1991.      *
  1992.      * @param   row                             the row to be edited
  1993.      * @param   column                          the column to be edited
  1994.      * @param   e                               event to pass into
  1995.      *                                          shouldSelectCell
  1996.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1997.      *                                          are not in the valid range
  1998.      * @return  false if for any reason the cell cannot be edited.
  1999.      */
  2000.     public boolean editCellAt(int row, int column, EventObject e){
  2001.         if (isEditing()) {
  2002.             // Try to stop the current editor
  2003.             if (cellEditor != null) {
  2004.                 boolean stopped = cellEditor.stopCellEditing();
  2005.                 if (!stopped)
  2006.                     return false;       // The current editor not resigning
  2007.             }
  2008.         }
  2009.  
  2010.         if (!isCellEditable(row, column))
  2011.             return false;
  2012.  
  2013.         TableCellEditor editor = getCellEditor(row, column);
  2014.         if (editor != null) {
  2015.             // prepare editor - size it then added it to the table
  2016.             editorComp = prepareEditor(editor, row, column);
  2017.  
  2018.             if (editor.isCellEditable(e)) {
  2019.                 editorComp.setBounds(getCellRect(row, column, false));
  2020.                 this.add(editorComp);
  2021.                 editorComp.validate();
  2022.  
  2023.                 setCellEditor(editor);
  2024.                 setEditingRow(row);
  2025.                 setEditingColumn(column);
  2026.                 editor.addCellEditorListener(this);
  2027.  
  2028.                 return true;
  2029.             }
  2030.         }
  2031.         return false;
  2032.     }
  2033.  
  2034.     /**
  2035.      * Returns  true is the table is editing a cell.
  2036.      *
  2037.      * @return  true is the table is editing a cell
  2038.      * @see     #editingColumn
  2039.      * @see     #editingRow
  2040.      */
  2041.     public boolean isEditing() {
  2042.         return (cellEditor == null)? false : true;
  2043.     }
  2044.  
  2045.     /**
  2046.      * If the receiver is currently editing this will return the Component
  2047.      * that was returned from the CellEditor.
  2048.      *
  2049.      * @return  Component handling editing session
  2050.      */
  2051.     public Component getEditorComponent() {
  2052.         return editorComp;
  2053.     }
  2054.  
  2055.     /**
  2056.      * This returns the index of the editing column.
  2057.      *
  2058.      * @return  the index of the column being edited
  2059.      * @see #editingRow
  2060.      */
  2061.     public int getEditingColumn() {
  2062.         return editingColumn;
  2063.     }
  2064.  
  2065.     /**
  2066.      * Returns the index of the editing row.
  2067.      *
  2068.      * @return  the index of the row being edited
  2069.      * @see #editingColumn
  2070.      */
  2071.     public int getEditingRow() {
  2072.         return editingRow;
  2073.     }
  2074.  
  2075. //
  2076. // Managing TableUI
  2077. //
  2078.  
  2079.     /**
  2080.      * Returns the L&F object that renders this component.
  2081.      *
  2082.      * @return the TableUI object that renders this component
  2083.      */
  2084.     public TableUI getUI() {
  2085.         return (TableUI)ui;
  2086.     }
  2087.  
  2088.     /**
  2089.      * Sets the L&F object that renders this component.
  2090.      *
  2091.      * @param ui  the TableUI L&F object
  2092.      * @see UIDefaults#getUI
  2093.      */
  2094.     public void setUI(TableUI ui) {
  2095.         if (this.ui != ui) {
  2096.             super.setUI(ui);
  2097.             repaint();
  2098.         }
  2099.     }
  2100.  
  2101.     private void updateSubComponentUI(Object componentShell) {
  2102.         if (componentShell == null) {
  2103.             return;
  2104.         }
  2105.         Component component = null;
  2106.         if (componentShell instanceof Component) {
  2107.             component = (Component)componentShell;
  2108.         }
  2109.         if (componentShell instanceof DefaultCellEditor) {
  2110.             component = ((DefaultCellEditor)componentShell).getComponent();
  2111.         }
  2112.  
  2113.         if (component != null && component instanceof JComponent) {
  2114.             ((JComponent)component).updateUI();
  2115.         }
  2116.     }
  2117.  
  2118.     /**
  2119.      * Notification from the UIManager that the L&F has changed.
  2120.      * Replaces the current UI object with the latest version from the
  2121.      * UIManager.
  2122.      *
  2123.      * @see JComponent#updateUI
  2124.      */
  2125.     public void updateUI() {
  2126.         // Update the UIs of the cell renderers, cell editors and header renderers.
  2127.         TableColumnModel cm = getColumnModel();
  2128.         for(int column = 0; column < cm.getColumnCount(); column++) {
  2129.             TableColumn aColumn = cm.getColumn(column);
  2130.            // updateSubComponentUI(aColumn.getCellRenderer());
  2131.             updateSubComponentUI(aColumn.getCellEditor());
  2132.            // updateSubComponentUI(aColumn.getHeaderRenderer());
  2133.         }
  2134.  
  2135.         // Update the UIs of all the default renderers.
  2136.         /*
  2137.         Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
  2138.         while (defaultRenderers.hasMoreElements()) {
  2139.             updateSubComponentUI(defaultRenderers.nextElement());
  2140.         }
  2141.         */
  2142.  
  2143.         // Update the UIs of all the default editors.
  2144.         Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
  2145.         while (defaultEditors.hasMoreElements()) {
  2146.             updateSubComponentUI(defaultEditors.nextElement());
  2147.         }
  2148.  
  2149.         setUI((TableUI)UIManager.getUI(this));
  2150.         resizeAndRepaint();
  2151.         invalidate();//PENDING
  2152.     }
  2153.  
  2154.     /**
  2155.      * Returns the name of the L&F class that renders this component.
  2156.      *
  2157.      * @return "TableUI"
  2158.      * @see JComponent#getUIClassID
  2159.      * @see UIDefaults#getUI
  2160.      */
  2161.     public String getUIClassID() {
  2162.         return uiClassID;
  2163.     }
  2164.  
  2165.  
  2166. //
  2167. // Managing models
  2168. //
  2169.  
  2170.     /**
  2171.      * Sets the data model for this table to <I>newModel</I> and registers
  2172.      * with for listner notifications from the new data model.
  2173.      *
  2174.      * @param   newModel        the new data source for this table
  2175.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2176.      * @see     #getModel
  2177.      * @beaninfo
  2178.      * description: The model that is the source of the data for this view.
  2179.      */
  2180.     public void setModel(TableModel newModel) {
  2181.         TableModel oldModel = dataModel;
  2182.  
  2183.         if (newModel == null)
  2184.             throw new IllegalArgumentException("Cannot set a null TableModel");
  2185.  
  2186.         if (newModel != oldModel) {
  2187.             if (oldModel != null)
  2188.                 oldModel.removeTableModelListener(this);
  2189.             dataModel = newModel;
  2190.             newModel.addTableModelListener(this);
  2191.             // If this method is called from the JTable constructor,
  2192.             // the column model will be null. In this case we can't use
  2193.             // the usual methods to update the internal state. In all other
  2194.             // cases, use the usual tableChanged() method to reconfigure
  2195.             // the JTable for the new model.
  2196.             if (getColumnModel() != null) {
  2197.                 tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW));
  2198.             }
  2199.         firePropertyChange("model", oldModel, newModel);
  2200.         }
  2201.     }
  2202.  
  2203.     /**
  2204.      * Returns the <B>TableModel</B> that provides the data displayed by
  2205.      * the receiver.
  2206.      *
  2207.      * @return  the object that provides the data displayed by the receiver
  2208.      * @see     #setModel
  2209.      */
  2210.     public TableModel getModel() {
  2211.         return dataModel;
  2212.     }
  2213.  
  2214.     /**
  2215.      * Sets the column model for this table to <I>newModel</I> and registers
  2216.      * with for listner notifications from the new column model. Also sets
  2217.      * the column model of the JTableHeader to <I>newModel</I>.
  2218.      *
  2219.      * @param   newModel        the new data source for this table
  2220.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2221.      * @see     #getColumnModel
  2222.      * @beaninfo
  2223.      * description: The object governing the way columns appear in the view.
  2224.      */
  2225.     public void setColumnModel(TableColumnModel newModel) {
  2226.         if (newModel == null) {
  2227.             throw new IllegalArgumentException("Cannot set a null ColumnModel");
  2228.         }
  2229.  
  2230.         TableColumnModel oldModel = columnModel;
  2231.         if (newModel != oldModel) {
  2232.             if (oldModel != null)
  2233.                 oldModel.removeColumnModelListener(this);
  2234.  
  2235.             columnModel = newModel;
  2236.             newModel.addColumnModelListener(this);
  2237.  
  2238.  
  2239.             // Set the column model of the header as well.
  2240.             if (tableHeader != null) {
  2241.                 tableHeader.setColumnModel(newModel);
  2242.             }
  2243.  
  2244.         firePropertyChange("columnModel", oldModel, newModel);
  2245.             resizeAndRepaint();
  2246.         }
  2247.     }
  2248.  
  2249.     /**
  2250.      * Returns the <B>TableColumnModel</B> that contains all column inforamtion
  2251.      * of this table.
  2252.      *
  2253.      * @return  the object that provides the column state of the table
  2254.      * @see     #setColumnModel
  2255.      */
  2256.     public TableColumnModel getColumnModel() {
  2257.         return columnModel;
  2258.     }
  2259.  
  2260.     /**
  2261.      * Sets the row selection model for this table to <I>newModel</I>
  2262.      * and registers with for listner notifications from the new selection model.
  2263.      *
  2264.      * @param   newModel        the new selection model
  2265.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2266.      * @see     #getSelectionModel
  2267.      * @beaninfo
  2268.      * description: The selection model for rows.
  2269.      */
  2270.     public void setSelectionModel(ListSelectionModel newModel) {
  2271.         if (newModel == null) {
  2272.             throw new IllegalArgumentException("Cannot set a null SelectionModel");
  2273.         }
  2274.  
  2275.         ListSelectionModel oldModel = selectionModel;
  2276.  
  2277.         if (newModel != oldModel) {
  2278.             if (oldModel != null) {
  2279.                 oldModel.removeListSelectionListener(this);
  2280.             }
  2281.  
  2282.             selectionModel = newModel;
  2283.  
  2284.             if (newModel != null) {
  2285.                 newModel.addListSelectionListener(this);
  2286.             }
  2287.         firePropertyChange("selectionModel", oldModel, newModel);
  2288.             repaint();
  2289.         }
  2290.     }
  2291.  
  2292.     /**
  2293.      * Returns the <B>ListSelectionModel</B> that is used to maintain row
  2294.      * selection state.
  2295.      *
  2296.      * @return  the object that provides row selection state.  Or <B>null</B>
  2297.      *          if row selection is not allowed.
  2298.      * @see     #setSelectionModel
  2299.      */
  2300.     public ListSelectionModel getSelectionModel() {
  2301.         return selectionModel;
  2302.     }
  2303.  
  2304. //
  2305. // Implementing TableModelListener interface
  2306. //
  2307.  
  2308.     /**
  2309.      * The TableModelEvent should be constructed in the co-ordinate system
  2310.      * of the model, the appropriate mapping to the view co-ordinate system
  2311.      * is performed by the JTable when it recieves the event.
  2312.      */
  2313.     public void tableChanged(TableModelEvent e) {
  2314.         if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
  2315.             // The whole thing changed
  2316.             clearSelection();
  2317.  
  2318.             if (getAutoCreateColumnsFromModel())
  2319.                 createDefaultColumnsFromModel();
  2320.  
  2321.             resizeAndRepaint();
  2322.             if (tableHeader != null) {
  2323.                 tableHeader.resizeAndRepaint();
  2324.             }
  2325.             return;
  2326.         }
  2327.  
  2328.         if (e.getType() == TableModelEvent.INSERT) {
  2329.             tableRowsInserted(e);
  2330.             return;
  2331.         }
  2332.  
  2333.         if (e.getType() == TableModelEvent.DELETE) {
  2334.             tableRowsDeleted(e);
  2335.             return;
  2336.         }
  2337.  
  2338.         int modelColumn = e.getColumn();
  2339.         int start = e.getFirstRow();
  2340.         int end = e.getLastRow();
  2341.  
  2342.         if (start == TableModelEvent.HEADER_ROW) {
  2343.             start = 0;
  2344.             end = Integer.MAX_VALUE;
  2345.         }
  2346.  
  2347.         int rowHeight = getRowHeight() + rowMargin;
  2348.         Rectangle dirtyRegion;
  2349.         if (modelColumn == TableModelEvent.ALL_COLUMNS) {
  2350.             // 1 or more rows changed
  2351.             dirtyRegion = new Rectangle(0, start * rowHeight,
  2352.                                         getColumnModel().getTotalColumnWidth(), 0);
  2353.         }
  2354.         else {
  2355.             // A cell or column of cells has changed.
  2356.             // Unlike the rest of the methods in the JTable, the TableModelEvent
  2357.             // uses the co-ordinate system of the model instead of the view.
  2358.             // This is the only place in the JTable where this "reverse mapping"
  2359.             // is used.
  2360.             int column = convertColumnIndexToView(modelColumn);
  2361.             dirtyRegion = getCellRect(start, column, false);
  2362.         }
  2363.  
  2364.         // Now adjust the height of the dirty region according to the value of "end".
  2365.         // Check for Integer.MAX_VALUE as this will cause an overflow.
  2366.         if (end != Integer.MAX_VALUE) {
  2367.             dirtyRegion.height = (end-start+1)*rowHeight;
  2368.             repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2369.         }
  2370.         // In fact, if the end is Integer.MAX_VALUE we need to revalidate anyway
  2371.         // because the scrollbar may need repainting.
  2372.         else {
  2373.             resizeAndRepaint();
  2374.         }
  2375.     }
  2376.  
  2377.     /*
  2378.      * Invoked when rows have been inserted into the table.
  2379.      *
  2380.      * @param e the TableModelEvent encapsulating the insertion
  2381.      */
  2382.     private void tableRowsInserted(TableModelEvent e) {
  2383.         int start = e.getFirstRow();
  2384.         int end = e.getLastRow();
  2385.         if (start < 0)
  2386.             start = 0;
  2387.  
  2388.         // 1 or more rows added, so we have to repaint from the first
  2389.         // new row to the end of the table.  (Everything shifts down)
  2390.         int rowHeight = getRowHeight() + rowMargin;
  2391.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2392.                                         getColumnModel().getTotalColumnWidth(),
  2393.                                            (getRowCount()-start) * rowHeight);
  2394.  
  2395.         // Adjust the selection to account for the new rows
  2396.         if (selectionModel != null) {
  2397.             if (end < 0)
  2398.                 end = getRowCount()-1;
  2399.             int length = end - start + 1;
  2400.  
  2401.             selectionModel.insertIndexInterval(start, length, true);
  2402.         }
  2403.         revalidate();
  2404.         // PENDING(philip) Find a way to stop revalidate calling repaint
  2405.         // repaint(drawRect);
  2406.     }
  2407.  
  2408.     /*
  2409.      * Invoked when rows have been removed from the table.
  2410.      *
  2411.      * @param e the TableModelEvent encapsulating the deletion
  2412.      */
  2413.     private void tableRowsDeleted(TableModelEvent e) {
  2414.         int start = e.getFirstRow();
  2415.         int end = e.getLastRow();
  2416.         if (start < 0)
  2417.             start = 0;
  2418.  
  2419.         int deletedCount = e.getLastRow() - end + 1;
  2420.         int previousRowCount = getRowCount() + deletedCount;
  2421.         // 1 or more rows added, so we have to repaint from the first
  2422.         // new row to the end of the table.  (Everything shifts up)
  2423.         int rowHeight = getRowHeight() + rowMargin;
  2424.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2425.                                         getColumnModel().getTotalColumnWidth(),
  2426.                                         (previousRowCount - start) * rowHeight);
  2427.  
  2428.         // Adjust the selection to account for the new rows
  2429.         if (selectionModel != null) {
  2430.             if (end < 0)
  2431.                 end = getRowCount()-1;
  2432.  
  2433.             selectionModel.removeIndexInterval(start, end);
  2434.         }
  2435.         revalidate();
  2436.         // PENDING(philip) Find a way to stop revalidate calling repaint
  2437.         // repaint(drawRect);
  2438.     }
  2439.  
  2440. //
  2441. // Implementing TableColumnModelListener interface
  2442. //
  2443.  
  2444.     /**
  2445.      * Tells listeners that a column was added to the model.
  2446.      *
  2447.      * @see TableColumnModelListener
  2448.      */
  2449.     public void columnAdded(TableColumnModelEvent e) {
  2450.         // If I'm currently editing, then I should stop editing
  2451.         if (isEditing()) {
  2452.             removeEditor();
  2453.         }
  2454.         resizeAndRepaint();
  2455.     }
  2456.  
  2457.     /**
  2458.      * Tells listeners that a column was removed from the model.
  2459.      *
  2460.      * @see TableColumnModelListener
  2461.      */
  2462.     public void columnRemoved(TableColumnModelEvent e) {
  2463.         // If I'm currently editing, then I should stop editing
  2464.         if (isEditing()) {
  2465.             removeEditor();
  2466.         }
  2467.         resizeAndRepaint();
  2468.     }
  2469.  
  2470.     /**
  2471.      * Tells listeners that a column was repositioned.
  2472.      *
  2473.      * @see TableColumnModelListener
  2474.      */
  2475.     public void columnMoved(TableColumnModelEvent e) {
  2476.         // If I'm currently editing, then I should stop editing
  2477.         if (isEditing()) {
  2478.             removeEditor();
  2479.         }
  2480.         repaint();
  2481.     }
  2482.  
  2483.     /**
  2484.      * Tells listeners that a column was moved due to a margin change.
  2485.      *
  2486.      * @see TableColumnModelListener
  2487.      */
  2488.     public void columnMarginChanged(ChangeEvent e) {
  2489.         // If I'm currently editing, then I should stop editing
  2490.         if (isEditing()) {
  2491.             removeEditor();
  2492.         }
  2493.         resizeAndRepaint();
  2494.     }
  2495.  
  2496.     /**
  2497.      * Tells listeners that the selection model of the
  2498.      * TableColumnModel changed.
  2499.      *
  2500.      * @see TableColumnModelListener
  2501.      */
  2502.     public void columnSelectionChanged(ListSelectionEvent e) {
  2503.         int firstIndex = e.getFirstIndex();
  2504.         int lastIndex = e.getLastIndex();
  2505.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2506.             repaint();
  2507.         }
  2508.         Rectangle firstColumnRect = getCellRect(0, firstIndex, false);
  2509.         Rectangle lastColumnRect = getCellRect(getRowCount(), lastIndex, false);
  2510.         Rectangle dirtyRegion = firstColumnRect.union(lastColumnRect);
  2511.         // This marks this entire column as dirty but the painting system will
  2512.         // intersect this with the clip rect of the viewport and redraw only
  2513.         // the visible cells.
  2514.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2515.     }
  2516.  
  2517. //
  2518. // Implementing ListSelectionListener interface
  2519. //
  2520.  
  2521.     /**
  2522.      * Invoked when the selection changes -- repaints to show the new
  2523.      * selection.
  2524.      *
  2525.      * @see ListSelectionListener
  2526.      */
  2527.     public void valueChanged(ListSelectionEvent e) {
  2528.         int firstIndex = e.getFirstIndex();
  2529.         int lastIndex = e.getLastIndex();
  2530.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2531.             repaint();
  2532.         }
  2533.         Rectangle firstRowRect = getCellRect(firstIndex, 0, false);
  2534.         Rectangle lastRowRect = getCellRect(lastIndex, getColumnCount(), false);
  2535.         Rectangle dirtyRegion = firstRowRect.union(lastRowRect);
  2536.         // This marks this entire row as dirty but the painting system will
  2537.         // intersect this with the clip rect of the viewport and redraw only
  2538.         // the visible cells.
  2539.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2540.     }
  2541.  
  2542. //
  2543. // Implementing the CellEditorListener interface
  2544. //
  2545.  
  2546.     /**
  2547.      * Invoked when editing is finished. The changes are saved, the
  2548.      * editor object is discarded, and the cell is rendered once again.
  2549.      *
  2550.      * @see CellEditorListener
  2551.      */
  2552.     public void editingStopped(ChangeEvent e) {
  2553.         // Take in the new value
  2554.         TableCellEditor editor = getCellEditor();
  2555.         if (editor != null) {
  2556.             Object value = editor.getCellEditorValue();
  2557.             setValueAt(value, editingRow, editingColumn);
  2558.  
  2559.             removeEditor();
  2560.         }
  2561.     }
  2562.  
  2563.     /**
  2564.      * Invoked when editing is canceled. The editor object is discarded
  2565.      * and the cell is rendered once again.
  2566.      *
  2567.      * @see CellEditorListener
  2568.      */
  2569.     public void editingCanceled(ChangeEvent e) {
  2570.         removeEditor();
  2571.     }
  2572.  
  2573. //
  2574. // Implementing the Scrollable interface
  2575. //
  2576.  
  2577.     /**
  2578.      * Sets the preferred size of the viewport for this table.
  2579.      *
  2580.      * @param size  a Dimension object specifying the preferredSize of a
  2581.      *              JViewport whose view is this table
  2582.      * @see Scrollable#getPreferredScrollableViewportSize
  2583.      * @beaninfo
  2584.      * description: The preferred size of the viewport.
  2585.      */
  2586.     public void setPreferredScrollableViewportSize(Dimension size) {
  2587.         preferredViewportSize = size;
  2588.     }
  2589.  
  2590.     /**
  2591.      * Returns the preferred size of the viewport for this table.
  2592.      *
  2593.      * @return a Dimension object containing the preferredSize of the JViewport
  2594.      *         which displays this table
  2595.      * @see Scrollable#getPreferredScrollableViewportSize
  2596.      */
  2597.     public Dimension getPreferredScrollableViewportSize() {
  2598.         return preferredViewportSize;
  2599.     }
  2600.  
  2601.     /**
  2602.      * Returns the scroll increment that completely exposes one new row
  2603.      * or column (depending on the orientation).
  2604.      * <p>
  2605.      * This method is called each time the user requests a unit scroll.
  2606.      *
  2607.      * @param visibleRect The view area visible within the viewport
  2608.      * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
  2609.      * @param direction Less than zero to scroll up/left, greater than zero for down/right.
  2610.      * @return The "unit" increment for scrolling in the specified direction
  2611.      * @see Scrollable#getScrollableUnitIncrement
  2612.      */
  2613.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
  2614.                                           int direction) {
  2615.         // PENDING(alan): do something smarter
  2616.         if (orientation == SwingConstants.HORIZONTAL) {
  2617.             return 100;
  2618.         }
  2619.         return rowHeight + rowMargin;
  2620.     }
  2621.  
  2622.     /**
  2623.      * Returns The visibleRect.height or visibleRect.width, depending on the
  2624.      * table's orientation.
  2625.      *
  2626.      * @return The visibleRect.height or visibleRect.width per the orientation.
  2627.      * @see Scrollable#getScrollableBlockIncrement
  2628.      */
  2629.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
  2630.                                            int direction) {
  2631.         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
  2632.             visibleRect.width;
  2633.     }
  2634.  
  2635.     /**
  2636.      * Returns false to indicate that the width of the viewport does not
  2637.      * determine the width of the table.
  2638.      *
  2639.      * @return false
  2640.      * @see Scrollable#getScrollableTracksViewportWidth
  2641.      */
  2642.     public boolean getScrollableTracksViewportWidth() {
  2643.         return !(autoResizeMode == AUTO_RESIZE_OFF);
  2644.     }
  2645.  
  2646.     /**
  2647.      * Returns false to indicate that the height of the viewport does not
  2648.      * determine the height of the table.
  2649.      *
  2650.      * @return false
  2651.      * @see Scrollable#getScrollableTracksViewportHeight
  2652.      */
  2653.     public boolean getScrollableTracksViewportHeight() {
  2654.         return false;
  2655.     }
  2656.  
  2657. //
  2658. // Protected Methods
  2659. //
  2660.  
  2661.     private class CheckBoxRenderer extends JCheckBox implements TableCellRenderer
  2662.     {
  2663.         public Component getTableCellRendererComponent(JTable table, Object value,
  2664.                          boolean isSelected, boolean hasFocus, int row, int column) {
  2665.         if (isSelected) {
  2666.             setForeground(table.getSelectionForeground());
  2667.             super.setBackground(table.getSelectionBackground());
  2668.         }
  2669.         else {
  2670.             setForeground(table.getForeground());
  2671.             setBackground(table.getBackground());
  2672.         }
  2673.             setSelected((value != null && ((Boolean)value).booleanValue()));
  2674.             return this;
  2675.         }
  2676.     }
  2677.  
  2678.     protected void createDefaultRenderers() {
  2679.         defaultRenderersByColumnClass = new Hashtable();
  2680.  
  2681.         // Objects
  2682.         DefaultTableCellRenderer label = new DefaultTableCellRenderer();
  2683.         setDefaultRenderer(Object.class, label);
  2684.  
  2685.     // Numbers
  2686.         DefaultTableCellRenderer numberRenderer = new DefaultTableCellRenderer() { 
  2687.         NumberFormat formatter = NumberFormat.getInstance(); 
  2688.             public void setValue(Object value) { 
  2689.         setText((value == null) ? "" : formatter.format(value)); 
  2690.         }
  2691.         };
  2692.         numberRenderer.setHorizontalAlignment(JLabel.RIGHT);
  2693.         setDefaultRenderer(Number.class, numberRenderer);
  2694.  
  2695.     // Dates
  2696.         DefaultTableCellRenderer dateRenderer = new DefaultTableCellRenderer() {
  2697.         DateFormat formatter = DateFormat.getDateInstance(); 
  2698.             public void setValue(Object value) { 
  2699.             setText((value == null) ? "" : formatter.format(value)); }
  2700.         };
  2701.         dateRenderer.setHorizontalAlignment(JLabel.RIGHT);
  2702.     setDefaultRenderer(Date.class, dateRenderer); 
  2703.  
  2704.         // Icons
  2705.         DefaultTableCellRenderer centeredLabel = new DefaultTableCellRenderer() {
  2706.             public void setValue(Object value) { setIcon((Icon)value); }
  2707.         };
  2708.         centeredLabel.setHorizontalAlignment(JLabel.CENTER);
  2709.         setDefaultRenderer(ImageIcon.class, centeredLabel);
  2710.  
  2711.         // Booleans
  2712. /*      DefaultTableCellRenderer booleanRenderer = new DefaultTableCellRenderer() {
  2713.             Icon trueIcon = UIManager.getIcon("CheckBox.icon");
  2714.             public void setValue(Object value) {
  2715.                 setIcon((value != null && ((Boolean)value).booleanValue()) ? trueIcon : null);
  2716.             }
  2717.         };
  2718.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2719.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2720. */
  2721.         CheckBoxRenderer booleanRenderer = new CheckBoxRenderer();
  2722.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2723.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2724.     }
  2725.  
  2726.     /**
  2727.      * Creates default cell editors for Objects, numbers, and boolean values.
  2728.      */
  2729.     protected void createDefaultEditors() {
  2730.         defaultEditorsByColumnClass = new Hashtable();
  2731.  
  2732.         // Objects
  2733.         JTextField textField = new JTextField();
  2734.         textField.setBorder(new LineBorder(Color.black));
  2735.         setDefaultEditor(Object.class, new DefaultCellEditor(textField));
  2736.  
  2737.         // Numbers
  2738.         JTextField rightAlignedTextField = new JTextField();
  2739.         rightAlignedTextField.setHorizontalAlignment(JTextField.RIGHT);
  2740.         rightAlignedTextField.setBorder(new LineBorder(Color.black));
  2741.         setDefaultEditor(Number.class, new DefaultCellEditor(rightAlignedTextField));
  2742.  
  2743.         // Booleans
  2744.         JCheckBox centeredCheckBox = new JCheckBox();
  2745.         centeredCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
  2746.         setDefaultEditor(Boolean.class, new DefaultCellEditor(centeredCheckBox));
  2747.     }
  2748.  
  2749.     /**
  2750.      * Initializes table properties to their default values.
  2751.      */
  2752.     protected void initializeLocalVars() {
  2753.         setOpaque(true);
  2754.         createDefaultRenderers();
  2755.         createDefaultEditors();
  2756.  
  2757.         setTableHeader(createDefaultTableHeader());
  2758.  
  2759.         setShowGrid(true);
  2760.         setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS);
  2761.         setRowHeight(16);
  2762.         rowMargin = 1;
  2763.         setRowSelectionAllowed(true);
  2764.         setCellSelectionEnabled(false);
  2765.         cellEditor = null;
  2766.         editingColumn = editingRow = -1;
  2767.         preferredViewportSize = new Dimension(450,400);
  2768.  
  2769.         // I'm registered to do tool tips so we can draw tips for the renderers
  2770.         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  2771.         toolTipManager.registerComponent(this);
  2772.  
  2773.         setAutoscrolls(true);
  2774.     }
  2775.  
  2776.     /**
  2777.      * Returns the default table model object which is
  2778.      * a DefaultTableModel.  Subclass can override this
  2779.      * method to return a different table model object.
  2780.      *
  2781.      * @return the default table model object
  2782.      */
  2783.     protected TableModel createDefaultDataModel() {
  2784.         return new DefaultTableModel();
  2785.     }
  2786.  
  2787.     /**
  2788.      * Returns the default column model object which is
  2789.      * a DefaultTableColumnModel.  Subclass can override this
  2790.      * method to return a different column model object
  2791.      *
  2792.      * @return the default column model object
  2793.      */
  2794.     protected TableColumnModel createDefaultColumnModel() {
  2795.         return new DefaultTableColumnModel();
  2796.     }
  2797.  
  2798.     /**
  2799.      * Returns the default selection model object which is
  2800.      * a DefaultListSelectionModel.  Subclass can override this
  2801.      * method to return a different selection model object.
  2802.      *
  2803.      * @return the default selection model object
  2804.      */
  2805.     protected ListSelectionModel createDefaultSelectionModel() {
  2806.         return new DefaultListSelectionModel();
  2807.     }
  2808.  
  2809.     /**
  2810.      * Returns the default table header object which is
  2811.      * a JTableHeader.  Subclass can override this
  2812.      * method to return a different table header object
  2813.      *
  2814.      * @return the default table header object
  2815.      */
  2816.     protected JTableHeader createDefaultTableHeader() {
  2817.         return new JTableHeader(columnModel);
  2818.     }
  2819.  
  2820.     /**
  2821.      * Equivalent to revalidate() followed by repaint().
  2822.      */
  2823.     protected void resizeAndRepaint() {
  2824.         revalidate();
  2825.         repaint(); 
  2826.     }
  2827.  
  2828.     /**
  2829.      * Return the cellEditor.
  2830.      *
  2831.      * @return the TableCellEditor that does the editing
  2832.      * @see #cellEditor
  2833.      */
  2834.     public TableCellEditor getCellEditor() {
  2835.         return cellEditor;
  2836.     }
  2837.  
  2838.     /**
  2839.      * Set the cellEditor variable.
  2840.      *
  2841.      * @param anEditor  the TableCellEditor that does the editing
  2842.      * @see #cellEditor
  2843.      */
  2844.     public void setCellEditor(TableCellEditor anEditor) {
  2845.     TableCellEditor oldEditor = cellEditor;
  2846.         cellEditor = anEditor;
  2847.     firePropertyChange("tableCellEditor", oldEditor, anEditor);
  2848.     }
  2849.  
  2850.     /**
  2851.      * Set the editingColumn variable.
  2852.      *
  2853.      * @see #editingColumn
  2854.      */
  2855.     public void setEditingColumn(int aColumn) {
  2856.         editingColumn = aColumn;
  2857.     }
  2858.  
  2859.     /**
  2860.      * Set the editingRow variable.
  2861.      *
  2862.      * @see #editingRow
  2863.      */
  2864.     public void setEditingRow(int aRow) {
  2865.         editingRow = aRow;
  2866.     }
  2867.  
  2868.     /**
  2869.      * Return an appropriate renderer for the cell specified by this this row and
  2870.      * column. If the TableColumn for this column has a non-null renderer, return that.
  2871.      * If not, find the class of the data in this column (using getColumnClass())
  2872.      * and return the default renderer for this type of data.
  2873.      *
  2874.      * @param row       the row of the cell to render, where 0 is the first
  2875.      * @param column    the column of the cell to render, where 0 is the first
  2876.      */
  2877.     public TableCellRenderer getCellRenderer(int row, int column) {
  2878.         TableColumn tableColumn = getColumnModel().getColumn(column);
  2879.         TableCellRenderer renderer = tableColumn.getCellRenderer();
  2880.         if (renderer == null) {
  2881.             renderer = getDefaultRenderer(getColumnClass(column));
  2882.         }
  2883.         return renderer;
  2884.     }
  2885.  
  2886.     /**
  2887.      * Prepares the specified renderer with an appropriate value
  2888.      * from the dataModel, and an appropriate selection value from
  2889.      * the selection models.
  2890.      *
  2891.      * @param renderer  the TableCellRenderer to prepare
  2892.      * @param row       the row of the cell to render, where 0 is the first
  2893.      * @param column    the column of the cell to render, where 0 is the first
  2894.      */
  2895.     public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
  2896.         Object value = getValueAt(row, column);
  2897.     boolean isSelected = isCellSelected(row, column);
  2898.     boolean rowIsAnchor = (getSelectedRow() == row);
  2899.     boolean columnIsAnchor = (getSelectedColumn() == column);
  2900.     boolean hasFocus = (rowIsAnchor && columnIsAnchor) && hasFocus();
  2901.  
  2902.     return renderer.getTableCellRendererComponent(this, value,
  2903.                                                   isSelected, hasFocus,
  2904.                                                   row, column);
  2905.     }
  2906.  
  2907.     /**
  2908.      * Return an appropriate editor for the cell specified by this this row and
  2909.      * column. If the TableColumn for this column has a non-null editor, return that.
  2910.      * If not, find the class of the data in this column (using getColumnClass())
  2911.      * and return the default editor for this type of data.
  2912.      *
  2913.      * @param row       the row of the cell to edit, where 0 is the first
  2914.      * @param column    the column of the cell to edit, where 0 is the first
  2915.      */
  2916.     public TableCellEditor getCellEditor(int row, int column) {
  2917.         TableColumn tableColumn = getColumnModel().getColumn(column);
  2918.         TableCellEditor editor = tableColumn.getCellEditor();
  2919.         if (editor == null) {
  2920.             editor = getDefaultEditor(getColumnClass(column));
  2921.         }
  2922.         return editor;
  2923.     }
  2924.  
  2925.  
  2926.     /**
  2927.      * Prepares the specified editor using the value at the specified cell.
  2928.      *
  2929.      * @param editor  the TableCellEditor to set up
  2930.      * @param row     the row of the cell to edit, where 0 is the first
  2931.      * @param column  the column of the cell to edit, where 0 is the first
  2932.      */
  2933.     public Component prepareEditor(TableCellEditor editor, int row, int column) {
  2934.         Object value = getValueAt(row, column);
  2935.         boolean isSelected = isCellSelected(row, column);
  2936.         Component comp = editor.getTableCellEditorComponent(this, value, isSelected,
  2937.                                                   row, column);
  2938.         if((comp != null) && (comp.getFont() == null)) {
  2939.             comp.setFont(getFont());
  2940.         }
  2941.         return comp;
  2942.     }
  2943.  
  2944.     /**
  2945.      * Discard the editor object and return the real estate it used to
  2946.      * cell rendering.
  2947.      */
  2948.     public void removeEditor() {
  2949.         TableCellEditor editor = getCellEditor();
  2950.         if(editor != null) {
  2951.             editor.removeCellEditorListener(this);
  2952.  
  2953.             // PENDING(alan): This is a temp work around for a JComboBox bug
  2954.             if (editorComp instanceof JComboBox) {
  2955.                 ((JComboBox)editorComp).hidePopup();
  2956.             }
  2957.  
  2958.             remove(editorComp);
  2959.  
  2960.             if (!(editorComp instanceof JComponent) ||
  2961.                  ((JComponent)editorComp).hasFocus()) {
  2962.                 requestFocus();
  2963.             }
  2964.  
  2965.             Rectangle cellRect = getCellRect(editingRow, editingColumn, false);
  2966.  
  2967.             setCellEditor(null);
  2968.             setEditingColumn(-1);
  2969.             setEditingRow(-1);
  2970.             editorComp = null;
  2971.  
  2972.             repaint(cellRect);
  2973.         }
  2974.     }
  2975.  
  2976. //
  2977. // Serialization
  2978. //
  2979.  
  2980.     private void readObject(ObjectInputStream s)
  2981.         throws IOException, ClassNotFoundException
  2982.     {
  2983.         s.defaultReadObject();
  2984.     if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  2985.         ui.installUI(this);
  2986.     }
  2987.         createDefaultRenderers();
  2988.         createDefaultEditors();
  2989.     }
  2990.  
  2991.  
  2992.     /**
  2993.      * Returns a string representation of this JTable. This method 
  2994.      * is intended to be used only for debugging purposes, and the 
  2995.      * content and format of the returned string may vary between      
  2996.      * implementations. The returned string may be empty but may not 
  2997.      * be <code>null</code>.
  2998.      * <P>
  2999.      * Overriding paramString() to provide information about the
  3000.      * specific new aspects of the JFC components.
  3001.      * 
  3002.      * @return  a string representation of this JTable.
  3003.      */
  3004.     protected String paramString() {
  3005.     String gridColorString = (gridColor != null ?
  3006.                   gridColor.toString() : "");
  3007.     String showHorizontalLinesString = (showHorizontalLines ?
  3008.                         "true" : "false");
  3009.     String showVerticalLinesString = (showVerticalLines ?
  3010.                       "true" : "false");
  3011.     String autoResizeModeString;
  3012.         if (autoResizeMode == AUTO_RESIZE_OFF) {
  3013.         autoResizeModeString = "AUTO_RESIZE_OFF";
  3014.     } else if (autoResizeMode == AUTO_RESIZE_NEXT_COLUMN) {
  3015.         autoResizeModeString = "AUTO_RESIZE_NEXT_COLUMN";
  3016.     } else if (autoResizeMode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) {
  3017.         autoResizeModeString = "AUTO_RESIZE_SUBSEQUENT_COLUMNS";
  3018.     } else if (autoResizeMode == AUTO_RESIZE_LAST_COLUMN) {
  3019.         autoResizeModeString = "AUTO_RESIZE_LAST_COLUMN";
  3020.     } else if (autoResizeMode == AUTO_RESIZE_ALL_COLUMNS)  {
  3021.         autoResizeModeString = "AUTO_RESIZE_ALL_COLUMNS";
  3022.     } else autoResizeModeString = "";
  3023.     String autoCreateColumnsFromModelString = (autoCreateColumnsFromModel ?
  3024.                            "true" : "false");
  3025.     String preferredViewportSizeString = (preferredViewportSize != null ?
  3026.                           preferredViewportSize.toString()
  3027.                           : "");
  3028.     String rowSelectionAllowedString = (rowSelectionAllowed ?
  3029.                         "true" : "false");
  3030.     String cellSelectionEnabledString = (cellSelectionEnabled ?
  3031.                         "true" : "false");
  3032.     String selectionForegroundString = (selectionForeground != null ?
  3033.                         selectionForeground.toString() :
  3034.                         "");
  3035.     String selectionBackgroundString = (selectionBackground != null ?
  3036.                         selectionBackground.toString() :
  3037.                         "");
  3038.  
  3039.     return super.paramString() +
  3040.     ",autoCreateColumnsFromModel=" + autoCreateColumnsFromModelString +
  3041.     ",autoResizeMode=" + autoResizeModeString +
  3042.     ",cellSelectionEnabled=" + cellSelectionEnabledString +
  3043.     ",editingColumn=" + editingColumn +
  3044.     ",editingRow=" + editingRow +
  3045.     ",gridColor=" + gridColorString +
  3046.     ",preferredViewportSize=" + preferredViewportSizeString +
  3047.     ",rowHeight=" + rowHeight +
  3048.     ",rowMargin=" + rowMargin +
  3049.     ",rowSelectionAllowed=" + rowSelectionAllowedString +
  3050.     ",selectionBackground=" + selectionBackgroundString +
  3051.     ",selectionForeground=" + selectionForegroundString +
  3052.     ",showHorizontalLines=" + showHorizontalLinesString +
  3053.     ",showVerticalLines=" + showVerticalLinesString;
  3054.     }
  3055.  
  3056.     /**
  3057.      * We override this method, whose implementation in JComponent 
  3058.      * returns false, to return true. This allows us to give a special 
  3059.      * meaning to TAB and SHIFT-TAB in the JTable. 
  3060.      */
  3061.     public boolean isManagingFocus() {
  3062.         return true;
  3063.     }    
  3064.  
  3065. /////////////////
  3066. // Accessibility support
  3067. ////////////////
  3068.  
  3069.     /**
  3070.      * Get the AccessibleContext associated with this JComponent
  3071.      *
  3072.      * @return the AccessibleContext of this JComponent
  3073.      */
  3074.     public AccessibleContext getAccessibleContext() {
  3075.         if (accessibleContext == null) {
  3076.             accessibleContext = new AccessibleJTable();
  3077.         }
  3078.         return accessibleContext;
  3079.     }
  3080.  
  3081.     //
  3082.     // *** should also implement AccessibleSelction?
  3083.     // *** and what's up with keyboard navigation/manipulation?
  3084.     //
  3085.     /**
  3086.      * The class used to obtain the accessible role for this object.
  3087.      * <p>
  3088.      * <strong>Warning:</strong>
  3089.      * Serialized objects of this class will not be compatible with
  3090.      * future Swing releases.  The current serialization support is appropriate
  3091.      * for short term storage or RMI between applications running the same
  3092.      * version of Swing.  A future release of Swing will provide support for
  3093.      * long term persistence.
  3094.      */
  3095.     protected class AccessibleJTable extends AccessibleJComponent
  3096.     implements AccessibleSelection, ListSelectionListener, TableModelListener,
  3097.     TableColumnModelListener, CellEditorListener, PropertyChangeListener  {
  3098.  
  3099.         int lastSelectedRow;
  3100.         int lastSelectedCol;
  3101.  
  3102.         AccessibleJTable() {
  3103.             super();
  3104.         JTable.this.addPropertyChangeListener(this);
  3105.             JTable.this.getSelectionModel().addListSelectionListener(this);
  3106.             TableColumnModel tcm = JTable.this.getColumnModel();
  3107.             tcm.addColumnModelListener(this);
  3108.         tcm.getSelectionModel().addListSelectionListener(this);
  3109.             JTable.this.getModel().addTableModelListener(this);
  3110.             lastSelectedRow = JTable.this.getSelectedRow();
  3111.             lastSelectedCol = JTable.this.getSelectedColumn();
  3112.         }
  3113.  
  3114.     // Listeners to track model, etc. changes to as to re-place the other
  3115.     // listeners
  3116.  
  3117.         /**
  3118.      * Track changes to selection model, column model, etc. so as to
  3119.      * be able to re-place listeners on those in order to pass on
  3120.      * information to the Accessibility PropertyChange mechanism
  3121.      */
  3122.         public void propertyChange(PropertyChangeEvent e) {
  3123.         String name = e.getPropertyName();
  3124.         Object oldValue = e.getOldValue();
  3125.         Object newValue = e.getNewValue();
  3126.  
  3127.             // re-set tableModel listeners
  3128.         if (name.compareTo("model") == 0) {
  3129.  
  3130.         if (oldValue != null && oldValue instanceof TableModel) {
  3131.             ((TableModel) oldValue).removeTableModelListener(this);
  3132.         }
  3133.         if (newValue != null && newValue instanceof TableModel) {
  3134.             ((TableModel) newValue).addTableModelListener(this);
  3135.         }
  3136.  
  3137.             // re-set selectionModel listeners
  3138.         } else if (name.compareTo("selectionModel") == 0) {
  3139.  
  3140.         Object source = e.getSource();
  3141.         if (source == JTable.this) {    // row selection model
  3142.  
  3143.             if (oldValue != null && 
  3144.             oldValue instanceof ListSelectionModel) {
  3145.             ((ListSelectionModel) oldValue).removeListSelectionListener(this);
  3146.             }
  3147.             if (newValue != null && 
  3148.             newValue instanceof ListSelectionModel) {
  3149.             ((ListSelectionModel) newValue).addListSelectionListener(this);
  3150.             }
  3151.  
  3152.         } else if (source == JTable.this.getColumnModel()) {
  3153.  
  3154.             if (oldValue != null && 
  3155.             oldValue instanceof ListSelectionModel) {
  3156.             ((ListSelectionModel) oldValue).removeListSelectionListener(this);
  3157.             }
  3158.             if (newValue != null && 
  3159.             newValue instanceof ListSelectionModel) {
  3160.             ((ListSelectionModel) newValue).addListSelectionListener(this);
  3161.             }
  3162.  
  3163.         } else {
  3164.           //        System.out.println("!!! Bug in source of selectionModel propertyChangeEvent");
  3165.         }
  3166.  
  3167.             // re-set columnModel listeners 
  3168.         // and column's selection property listener as well
  3169.         } else if (name.compareTo("columnModel") == 0) {
  3170.  
  3171.         if (oldValue != null && oldValue instanceof TableColumnModel) {
  3172.             TableColumnModel tcm = (TableColumnModel) oldValue;
  3173.             tcm.removeColumnModelListener(this);
  3174.             tcm.getSelectionModel().removeListSelectionListener(this);
  3175.         }
  3176.         if (newValue != null && newValue instanceof TableColumnModel) {
  3177.             TableColumnModel tcm = (TableColumnModel) oldValue;
  3178.             tcm.addColumnModelListener(this);
  3179.             tcm.getSelectionModel().addListSelectionListener(this);
  3180.         }
  3181.  
  3182.             // re-se cellEditor listeners 
  3183.         } else if (name.compareTo("tableCellEditor") == 0) {
  3184.  
  3185.         if (oldValue != null && oldValue instanceof TableCellEditor) {
  3186.             ((TableCellEditor) oldValue).removeCellEditorListener((CellEditorListener) this);
  3187.         }
  3188.         if (newValue != null && newValue instanceof TableCellEditor) {
  3189.             ((TableCellEditor) newValue).addCellEditorListener((CellEditorListener) this);
  3190.         }
  3191.         }
  3192.     }
  3193.  
  3194.  
  3195.     // Listeners to echo changes to the AccessiblePropertyChange mechanism
  3196.  
  3197.         /**
  3198.          * Track changes to the table contents
  3199.          */
  3200.         public void tableChanged(TableModelEvent e) {
  3201.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3202.                               null, null);
  3203.         }
  3204.  
  3205.         /**
  3206.          * Track changes to the table contents (row insertions)
  3207.          */
  3208.         public void tableRowsInserted(TableModelEvent e) {
  3209.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3210.                               null, null);
  3211.         }
  3212.  
  3213.         /**
  3214.          * Track changes to the table contents (row deletions)
  3215.          */
  3216.         public void tableRowsDeleted(TableModelEvent e) {
  3217.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3218.                               null, null);
  3219.         }
  3220.  
  3221.         /**
  3222.          * Track changes to the table contents (column insertions)
  3223.          */
  3224.         public void columnAdded(TableColumnModelEvent e) {
  3225.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3226.                               null, null);
  3227.         }
  3228.  
  3229.         /**
  3230.          * Track changes to the table contents (column deletions)
  3231.          */
  3232.         public void columnRemoved(TableColumnModelEvent e) {
  3233.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3234.                               null, null);
  3235.         }
  3236.  
  3237.         /**
  3238.          * Track changes of a column repositioning.
  3239.          *
  3240.          * @see TableColumnModelListener
  3241.          */
  3242.         public void columnMoved(TableColumnModelEvent e) {
  3243.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3244.                               null, null);
  3245.         }
  3246.  
  3247.         /**
  3248.          * Track changes of a column moving due to margin changes.
  3249.          *
  3250.          * @see TableColumnModelListener
  3251.          */
  3252.         public void columnMarginChanged(ChangeEvent e) {
  3253.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3254.                               null, null);
  3255.         }
  3256.  
  3257.         /**
  3258.          * Track that the selection model of the TableColumnModel changed.
  3259.          *
  3260.          * @see TableColumnModelListener
  3261.          */
  3262.         public void columnSelectionChanged(ListSelectionEvent e) {
  3263.             // we should now re-place our TableColumn listener
  3264.         }
  3265.  
  3266.         /**
  3267.          * Track changes to a cell's contents.
  3268.          *
  3269.          * Invoked when editing is finished. The changes are saved, the
  3270.          * editor object is discarded, and the cell is rendered once again.
  3271.          *
  3272.          * @see CellEditorListener
  3273.          */
  3274.         public void editingStopped(ChangeEvent e) {
  3275.            // it'd be great if we could figure out which cell, and pass that
  3276.            // somehow as a parameter
  3277.            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  3278.                               null, null);
  3279.         }
  3280.  
  3281.         /**
  3282.          * Invoked when editing is canceled. The editor object is discarded
  3283.          * and the cell is rendered once again.
  3284.          *
  3285.          * @see CellEditorListener
  3286.          */
  3287.         public void editingCanceled(ChangeEvent e) {
  3288.             // nothing to report, 'cause nothing changed
  3289.         }
  3290.  
  3291.         /**
  3292.          * Track changes to table cell selections
  3293.          */
  3294.         public void valueChanged(ListSelectionEvent e) {
  3295.             firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  3296.                                new Boolean(false), new Boolean(true));
  3297.  
  3298.             int selectedRow = JTable.this.getSelectedRow();
  3299.             int selectedCol = JTable.this.getSelectedColumn();
  3300.             if (selectedRow != lastSelectedRow ||
  3301.                 selectedCol != lastSelectedCol) {
  3302.                 Accessible oldA = getAccessibleAt(lastSelectedRow,
  3303.                                                   lastSelectedCol);
  3304.                 Accessible newA = getAccessibleAt(selectedRow, selectedCol);
  3305.                 firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
  3306.                                    oldA, newA);
  3307.                  lastSelectedRow = selectedRow;
  3308.                  lastSelectedCol = selectedCol;
  3309.              }
  3310.         }
  3311.  
  3312.  
  3313.  
  3314.  
  3315.     // AccessibleContext support
  3316.  
  3317.         /**
  3318.          * Get the AccessibleSelection associated with this object if one
  3319.          * exists.  Otherwise return null.
  3320.          *
  3321.          * @return the AccessibleSelection, or null
  3322.          */
  3323.         public AccessibleSelection getAccessibleSelection() {
  3324.             return this;
  3325.         }
  3326.  
  3327.         /**
  3328.          * Get the role of this object.
  3329.          *
  3330.          * @return an instance of AccessibleRole describing the role of the
  3331.          * object
  3332.          * @see AccessibleRole
  3333.          */
  3334.         public AccessibleRole getAccessibleRole() {
  3335.             return AccessibleRole.TABLE;
  3336.         }
  3337.  
  3338.         /**
  3339.          * Returns the Accessible child, if one exists, contained at the local
  3340.          * coordinate Point.
  3341.          *
  3342.          * @param p The point defining the top-left corner of the Accessible,
  3343.          * given in the coordinate space of the object's parent.
  3344.          * @return the Accessible, if it exists, at the specified location;
  3345.          * else null
  3346.          */
  3347.         public Accessible getAccessibleAt(Point p) {
  3348.             int column = columnAtPoint(p);
  3349.             int row = rowAtPoint(p);
  3350.  
  3351.             if ((column != -1) && (row != -1)) {
  3352.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3353.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3354.                 if (renderer == null) {
  3355.                     Class columnClass = getColumnClass(column);
  3356.                     renderer = getDefaultRenderer(columnClass);
  3357.                 }
  3358.                 Component component = renderer.getTableCellRendererComponent(
  3359.                                   JTable.this, null, false, false,
  3360.                                   row, column);
  3361.                 return new AccessibleJTableCell(JTable.this, row, column,
  3362.                       getAccessibleIndexAt(row, column));
  3363.             }
  3364.             return null;
  3365.         }
  3366.  
  3367.         /**
  3368.          * Returns the number of accessible children in the object.  If all
  3369.          * of the children of this object implement Accessible, than this
  3370.          * method should return the number of children of this object.
  3371.          *
  3372.          * @return the number of accessible children in the object.
  3373.          */
  3374.         public int getAccessibleChildrenCount() {
  3375.             return (JTable.this.getColumnCount() * JTable.this.getRowCount());
  3376.         }
  3377.  
  3378.         /**
  3379.          * Return the nth Accessible child of the object.
  3380.          *
  3381.          * @param i zero-based index of child
  3382.          * @return the nth Accessible child of the object
  3383.          */
  3384.         public Accessible getAccessibleChild(int i) {
  3385.             if (i < 0 || i >= getAccessibleChildrenCount()) {
  3386.                 return null;
  3387.             } else {
  3388.                 // children increase across, and then down, for tables
  3389.                 // (arbitrary decision)
  3390.                 int column = getAccessibleColumnAtIndex(i);
  3391.                 int row = getAccessibleRowAtIndex(i);
  3392.  
  3393.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3394.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3395.                 if (renderer == null) {
  3396.                     Class columnClass = getColumnClass(column);
  3397.                     renderer = getDefaultRenderer(columnClass);
  3398.                 }
  3399.                 Component component = renderer.getTableCellRendererComponent(
  3400.                                   JTable.this, null, false, false,
  3401.                                   row, column);
  3402.                 return new AccessibleJTableCell(JTable.this, row, column,
  3403.                       getAccessibleIndexAt(row, column));
  3404.             }
  3405.         }
  3406.  
  3407.     // AccessibleSelection support
  3408.  
  3409.         /**
  3410.          * Returns the number of Accessible children currently selected.
  3411.          * If no children are selected, the return value will be 0.
  3412.          *
  3413.          * @return the number of items currently selected.
  3414.          */
  3415.         public int getAccessibleSelectionCount() {
  3416.             int rowsSel = JTable.this.getSelectedRowCount();
  3417.             int colsSel = JTable.this.getSelectedColumnCount();
  3418.  
  3419.             if (JTable.this.cellSelectionEnabled) { // a contiguous block
  3420.                 return rowsSel * colsSel;
  3421.  
  3422.             } else {
  3423.                 // a column swath and a row swath, with a shared block
  3424.                 if (JTable.this.getRowSelectionAllowed() &&
  3425.                     JTable.this.getColumnSelectionAllowed()) {
  3426.                     return rowsSel * JTable.this.getColumnCount() +
  3427.                            colsSel * JTable.this.getRowCount() -
  3428.                            rowsSel * colsSel;
  3429.  
  3430.                 // just one or more rows in selection
  3431.                 } else if (JTable.this.getRowSelectionAllowed()) {
  3432.                     return rowsSel * JTable.this.getColumnCount();
  3433.  
  3434.                 // just one or more rows in selection
  3435.                 } else if (JTable.this.getColumnSelectionAllowed()) {
  3436.                     return colsSel * JTable.this.getRowCount();
  3437.  
  3438.                 } else {
  3439.                     return 0;    // JTable doesn't allow selections
  3440.                 }
  3441.             }
  3442.         }
  3443.  
  3444.         /**
  3445.          * Returns an Accessible representing the specified selected child
  3446.          * in the object.  If there isn't a selection, or there are
  3447.          * fewer children selected than the integer passed in, the return
  3448.          * value will be null.
  3449.          * <p>Note that the index represents the i-th selected child, which
  3450.          * is different from the i-th child.
  3451.          *
  3452.          * @param i the zero-based index of selected children
  3453.          * @return the i-th selected child
  3454.          * @see #getAccessibleSelectionCount
  3455.          */
  3456.         public Accessible getAccessibleSelection(int i) {
  3457.             if (i < 0 || i > getAccessibleSelectionCount()) {
  3458.                 return (Accessible) null;
  3459.             }
  3460.  
  3461.             int rowsSel = JTable.this.getSelectedRowCount();
  3462.             int colsSel = JTable.this.getSelectedColumnCount();
  3463.             int rowIndicies[] = getSelectedRows();
  3464.             int colIndicies[] = getSelectedColumns();
  3465.             int ttlCols = JTable.this.getColumnCount();
  3466.             int ttlRows = JTable.this.getRowCount();
  3467.             int r;
  3468.             int c;
  3469.  
  3470.             if (JTable.this.cellSelectionEnabled) { // a contiguous block
  3471.                 r = rowIndicies[i / colsSel];
  3472.                 c = colIndicies[i % colsSel];
  3473.                 return getAccessibleChild((r * ttlCols) + c);
  3474.             } else {
  3475.  
  3476.                 // a column swath and a row swath, with a shared block
  3477.                 if (JTable.this.getRowSelectionAllowed() &&
  3478.                     JTable.this.getColumnSelectionAllowed()) {
  3479.  
  3480.                     // Situation:
  3481.                     //   We have a table, like the 6x3 table below,
  3482.                     //   wherein three colums and one row selected
  3483.                     //   (selected cells marked with "*", unselected "0"):
  3484.                     //
  3485.                     //            0 * 0 * * 0
  3486.                     //            * * * * * *
  3487.                     //            0 * 0 * * 0
  3488.                     //
  3489.  
  3490.                     // State machine below walks through the array of
  3491.                     // selected rows in two states: in a selected row,
  3492.                     // and not in one; continuing until we are in a row
  3493.                     // in which the ith selection exists.  Then we return
  3494.                     // the appropriate cell.  In the state machine, we
  3495.                     // always do rows above the "current" selected row first,
  3496.                     // then the cells in the selected row.  If we're done
  3497.                     // with the state machine before finding the requested
  3498.                     // selected child, we handle the rows below the last
  3499.                     // selected row at the end.
  3500.                     //
  3501.                     int curIndex = i;
  3502.                     final int IN_ROW = 0;
  3503.                     final int NOT_IN_ROW = 1;
  3504.                     int state = (rowIndicies[0] == 0 ? IN_ROW : NOT_IN_ROW);
  3505.                     int j = 0;
  3506.                     int prevRow = -1;
  3507.                     while (j < rowIndicies.length) {
  3508.                         switch (state) {
  3509.  
  3510.                         case IN_ROW:   // on individual row full of selections
  3511.                             if (curIndex < ttlCols) { // it's here!
  3512.                                 c = curIndex % ttlCols;
  3513.                                 r = rowIndicies[j];
  3514.                                 return getAccessibleChild((r * ttlCols) + c);
  3515.                             } else {                               // not here
  3516.                                 curIndex -= ttlCols;
  3517.                             }
  3518.                             // is the next row in table selected or not?
  3519.                             if (j + 1 == rowIndicies.length ||
  3520.                                 rowIndicies[j] != rowIndicies[j+1] - 1) {
  3521.                                 state = NOT_IN_ROW;
  3522.                                 prevRow = rowIndicies[j];
  3523.                             }
  3524.                             j++;  // we didn't return earlier, so go to next row
  3525.                             break;
  3526.  
  3527.                         case NOT_IN_ROW:  // sparse bunch of rows of selections
  3528.                             if (curIndex <
  3529.                                 (colsSel * (rowIndicies[j] -
  3530.                                 (prevRow == -1 ? 0 : (prevRow + 1))))) {
  3531.  
  3532.                                 // it's here!
  3533.                                 c = colIndicies[curIndex % colsSel];
  3534.                                 r = (j > 0 ? rowIndicies[j-1] + 1 : 0)
  3535.                                     + curIndex / colsSel;
  3536.                                 return getAccessibleChild((r * ttlCols) + c);
  3537.                             } else {                               // not here
  3538.                                 curIndex -= colsSel * (rowIndicies[j] -
  3539.                                 (prevRow == -1 ? 0 : (prevRow + 1)));
  3540.                             }
  3541.                             state = IN_ROW;
  3542.                             break;
  3543.                         }
  3544.                     }
  3545.                     // we got here, so we didn't find it yet; find it in
  3546.                     // the last sparse bunch of rows
  3547.                     if (curIndex <
  3548.                         (colsSel * (ttlRows -
  3549.                         (prevRow == -1 ? 0 : (prevRow + 1))))) { // it's here!
  3550.                         c = colIndicies[curIndex % colsSel];
  3551.                         r = rowIndicies[j-1] + curIndex / colsSel + 1;
  3552.                         return getAccessibleChild((r * ttlCols) + c);
  3553.                     } else {                               // not here
  3554.                         // we shouldn't get to this spot in the code!
  3555. //                      System.out.println("Bug in AccessibleJTable.getAccessibleSelection()");
  3556.                     }
  3557.  
  3558.                 // one or more rows selected
  3559.                 } else if (JTable.this.getRowSelectionAllowed()) {
  3560.                     c = i % ttlCols;
  3561.                     r = rowIndicies[i / ttlCols];
  3562.                     return getAccessibleChild((r * ttlCols) + c);
  3563.  
  3564.                 // one or more columns selected
  3565.                 } else if (JTable.this.getColumnSelectionAllowed()) {
  3566.                     c = colIndicies[i % colsSel];
  3567.                     r = i / colsSel;
  3568.                     return getAccessibleChild((r * ttlCols) + c);
  3569.                 }
  3570.             }
  3571.             return (Accessible) null;
  3572.         }
  3573.  
  3574.         /**
  3575.          * Determines if the current child of this object is selected.
  3576.          *
  3577.          * @return true if the current child of this object is selected
  3578.          * @param i the zero-based index of the child in this Accessible object.
  3579.          * @see AccessibleContext#getAccessibleChild
  3580.          */
  3581.         public boolean isAccessibleChildSelected(int i) {
  3582.             int column = getAccessibleColumnAtIndex(i);
  3583.             int row = getAccessibleRowAtIndex(i);
  3584.             return JTable.this.isCellSelected(row, column);
  3585.         }
  3586.  
  3587.         /**
  3588.          * Adds the specified Accessible child of the object to the object's
  3589.          * selection.  If the object supports multiple selections,
  3590.          * the specified child is added to any existing selection, otherwise
  3591.          * it replaces any existing selection in the object.  If the
  3592.          * specified child is already selected, this method has no effect.
  3593.          *
  3594.          * This method only works on JTables which have individual cell
  3595.          * selection enabled.
  3596.          *
  3597.          * @param i the zero-based index of the child
  3598.          * @see AccessibleContext#getAccessibleChild
  3599.          */
  3600.         public void addAccessibleSelection(int i) {
  3601.             if (JTable.this.cellSelectionEnabled) {
  3602.                 int column = getAccessibleColumnAtIndex(i);
  3603.                 int row = getAccessibleRowAtIndex(i);
  3604.                 JTable.this.addRowSelectionInterval(row, row);
  3605.                 JTable.this.addColumnSelectionInterval(column, column);
  3606.             }
  3607.         }
  3608.  
  3609.         /**
  3610.          * Removes the specified child of the object from the object's
  3611.          * selection.  If the specified item isn't currently selected, this
  3612.          * method has no effect.
  3613.          *
  3614.          * This method only works on JTables which have individual cell
  3615.          * selection enabled.
  3616.          *
  3617.          * @param i the zero-based index of the child
  3618.          * @see AccessibleContext#getAccessibleChild
  3619.          */
  3620.         public void removeAccessibleSelection(int i) {
  3621.             if (JTable.this.cellSelectionEnabled) {
  3622.                 int column = getAccessibleColumnAtIndex(i);
  3623.                 int row = getAccessibleRowAtIndex(i);
  3624.                 JTable.this.removeRowSelectionInterval(row, row);
  3625.                 JTable.this.removeColumnSelectionInterval(column, column);
  3626.             }
  3627.         }
  3628.  
  3629.         /**
  3630.          * Clears the selection in the object, so that no children in the
  3631.          * object are selected.
  3632.          */
  3633.         public void clearAccessibleSelection() {
  3634.             JTable.this.clearSelection();
  3635.         }
  3636.  
  3637.         /**
  3638.          * Causes every child of the object to be selected, but only
  3639.          * if the JTable supports multiple selections, and if individual
  3640.          * cell selection is enabled.
  3641.          */
  3642.         public void selectAllAccessibleSelection() {
  3643.             if (JTable.this.cellSelectionEnabled) {
  3644.                 JTable.this.selectAll();
  3645.             }
  3646.         }
  3647.  
  3648. //        /**
  3649. //         * Get the AccessibleTable associated with this object if one
  3650. //         * exists.  Otherwise return null.
  3651. //         */
  3652. //        public AccessibleTable getAccessibleTable() {
  3653. //            return this;
  3654. //        }
  3655.  
  3656.  
  3657.     // AccessibleTable methods
  3658.  
  3659.         /*
  3660.          * Returns the total number of rows in the table
  3661.          *
  3662.          * @return the total number of rows in the table
  3663.          */
  3664.         private int getAccessibleRowCount() {
  3665.             return JTable.this.getRowCount();
  3666.         }
  3667.  
  3668.         /*
  3669.          * Returns the total number of columns in the table
  3670.          *
  3671.          * @return the total number of columns in the table
  3672.          */
  3673.         private int getAccessibleColumnCount() {
  3674.             return JTable.this.getColumnCount();
  3675.         }
  3676.  
  3677.         /*
  3678.          * Returns the row at a given index into the table
  3679.          *
  3680.          * @param i zero-based index into the table
  3681.          * @return the row at a given index
  3682.          */
  3683.         private int getAccessibleRowAtIndex(int i) {
  3684.             return (i / getAccessibleColumnCount());
  3685.         }
  3686.  
  3687.         /*
  3688.          * Returns the column at a given index into the table
  3689.          *
  3690.          * @param i zero-based index into the table
  3691.          * @return the column at a given index
  3692.          */
  3693.         private int getAccessibleColumnAtIndex(int i) {
  3694.             return (i % getAccessibleColumnCount());
  3695.         }
  3696.  
  3697.         /*
  3698.          * Returns the index at a given (row, column) in the table
  3699.          *
  3700.          * @param r zero-based row of the table
  3701.          * @param c zero-based column of the table
  3702.          * @return the index into the table
  3703.          */
  3704.         private int getAccessibleIndexAt(int r, int c) {
  3705.             return ((r * getAccessibleColumnCount()) + c);
  3706.         }
  3707.  
  3708.         /*
  3709.          * Returns the Accessible at a given (row, column) in the table
  3710.          *
  3711.          * @param r zero-based row of the table
  3712.          * @param c zero-based column of the table
  3713.          * @return the Accessible at the specified (row, column)
  3714.          */
  3715.         private Accessible getAccessibleAt(int r, int c) {
  3716.             return getAccessibleChild((r * getAccessibleColumnCount()) + c);
  3717.         }
  3718.  
  3719.         /*
  3720.          * Return the Accessible representing the row header, if
  3721.          * there is one (may be null).
  3722.          *
  3723.          * @param row zero-based row of the table
  3724.          * @return the Accessible header of the row
  3725.          */
  3726.         private Accessible getAccessibleRowHeader(int row) {
  3727.             return null;
  3728.         }
  3729.  
  3730.         /*
  3731.          * Return the Accessible representing the column header, if
  3732.          * there is one (may be null)
  3733.          *
  3734.          * @param column zero-based column of the table
  3735.          * @return the Accessible header of the column
  3736.          */
  3737.         private Accessible getAccessibleColumnHeader(int column) {
  3738.             JTableHeader header = JTable.this.getTableHeader();
  3739.             AccessibleContext ac = header.getAccessibleContext();
  3740.             if (ac != null) {
  3741.                 return ac.getAccessibleChild(column);
  3742.             } else {
  3743.                 return null;
  3744.             }
  3745.         }
  3746.  
  3747.  
  3748.         /**
  3749.          * The class used to obtain the AccessibleRole for a cell.
  3750.          */
  3751.         protected class AccessibleJTableCell extends AccessibleContext
  3752.             implements Accessible, AccessibleComponent {
  3753.  
  3754.             private JTable parent;
  3755.             private int row;
  3756.             private int column;
  3757.             private int index;
  3758.  
  3759.             /**
  3760.              *  Constructs an AccessiblJTableHeaaderEntry
  3761.              */
  3762.             public AccessibleJTableCell(JTable t, int r, int c, int i) {
  3763.                 parent = t;
  3764.                 row = r;
  3765.                 column = c;
  3766.                 index = i;
  3767.                 this.setAccessibleParent(parent);
  3768.             }
  3769.  
  3770.             /**
  3771.              * Get the AccessibleContext associated with this
  3772.              *
  3773.              * @return the AccessibleContext of this JComponent
  3774.              */
  3775.             public AccessibleContext getAccessibleContext() {
  3776.                 return this;
  3777.             }
  3778.  
  3779.             private AccessibleContext getCurrentAccessibleContext() {
  3780.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3781.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3782.                 if (renderer == null) {
  3783.                     Class columnClass = getColumnClass(column);
  3784.                     renderer = getDefaultRenderer(columnClass);
  3785.                 }
  3786.                 Component component = renderer.getTableCellRendererComponent(
  3787.                                   JTable.this, getValueAt(row, column), 
  3788.                   false, false, row, column);
  3789.                 if (component instanceof Accessible) {
  3790.                     return ((Accessible) component).getAccessibleContext();
  3791.                 } else {
  3792.                     return null;
  3793.                 }
  3794.             }
  3795.  
  3796.             private Component getCurrentComponent() {
  3797.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3798.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3799.                 if (renderer == null) {
  3800.                     Class columnClass = getColumnClass(column);
  3801.                     renderer = getDefaultRenderer(columnClass);
  3802.                 }
  3803.                 return renderer.getTableCellRendererComponent(
  3804.                                   JTable.this, null, false, false,
  3805.                                   row, column);
  3806.             }
  3807.  
  3808.         // AccessibleContext methods
  3809.  
  3810.             /**
  3811.              * Get the accessible name of this object.
  3812.              *
  3813.              * @return the localized name of the object; null if this
  3814.              * object does not have a name
  3815.              */
  3816.             public String getAccessibleName() {
  3817.                 AccessibleContext ac = getCurrentAccessibleContext();
  3818.                 if (ac != null) {
  3819.                     String name = ac.getAccessibleName();
  3820.                     if ((name != null) && (name != "")) {
  3821.                         return ac.getAccessibleName();
  3822.                     }
  3823.                 }
  3824.                 if ((accessibleName != null) && (accessibleName != "")) {
  3825.                     return accessibleName;
  3826.                 } else {
  3827.                     return parent.getValueAt(row, column).toString();
  3828.                 }
  3829.             }
  3830.  
  3831.             /**
  3832.              * Set the localized accessible name of this object.
  3833.              *
  3834.              * @param s the new localized name of the object.
  3835.              */
  3836.             public void setAccessibleName(String s) {
  3837.                 AccessibleContext ac = getCurrentAccessibleContext();
  3838.                 if (ac != null) {
  3839.                     ac.setAccessibleName(s);
  3840.                 } else {
  3841.                     super.setAccessibleName(s);
  3842.                 }
  3843.             }
  3844.  
  3845.             //
  3846.             // *** should check toolip text for desc. (needs MouseEvent)
  3847.             //
  3848.             /**
  3849.              * Get the accessible description of this object.
  3850.              *
  3851.              * @return the localized description of the object; null if
  3852.              * this object does not have a description
  3853.              */
  3854.             public String getAccessibleDescription() {
  3855.                 AccessibleContext ac = getCurrentAccessibleContext();
  3856.                 if (ac != null) {
  3857.                     return ac.getAccessibleDescription();
  3858.                 } else {
  3859.                     return super.getAccessibleDescription();
  3860.                 }
  3861.             }
  3862.  
  3863.             /**
  3864.              * Set the accessible description of this object.
  3865.              *
  3866.              * @param s the new localized description of the object
  3867.              */
  3868.             public void setAccessibleDescription(String s) {
  3869.                 AccessibleContext ac = getCurrentAccessibleContext();
  3870.                 if (ac != null) {
  3871.                     ac.setAccessibleDescription(s);
  3872.                 } else {
  3873.                     super.setAccessibleDescription(s);
  3874.                 }
  3875.             }
  3876.  
  3877.             /**
  3878.              * Get the role of this object.
  3879.              *
  3880.              * @return an instance of AccessibleRole describing the role of the object
  3881.              * @see AccessibleRole
  3882.              */
  3883.             public AccessibleRole getAccessibleRole() {
  3884.                 AccessibleContext ac = getCurrentAccessibleContext();
  3885.                 if (ac != null) {
  3886.                     return ac.getAccessibleRole();
  3887.                 } else {
  3888.                     return AccessibleRole.UNKNOWN;
  3889.                 }
  3890.             }
  3891.  
  3892.             /**
  3893.              * Get the state set of this object.
  3894.              *
  3895.              * @return an instance of AccessibleStateSet containing the
  3896.              * current state set of the object
  3897.              * @see AccessibleState
  3898.              */
  3899.             public AccessibleStateSet getAccessibleStateSet() {
  3900.                 AccessibleContext ac = getCurrentAccessibleContext();
  3901.         AccessibleStateSet as = null;
  3902.  
  3903.                 if (ac != null) {
  3904.                     as = ac.getAccessibleStateSet();
  3905.                 }
  3906.         if (as == null) {
  3907.                     as = new AccessibleStateSet();
  3908.                 }
  3909.         Rectangle rjt = JTable.this.getVisibleRect();
  3910.                 Rectangle rcell = JTable.this.getCellRect(row, column, false);
  3911.         if (rjt.intersects(rcell)) {
  3912.             as.add(AccessibleState.SHOWING);
  3913.                 } else {
  3914.                     if (as.contains(AccessibleState.SHOWING)) {
  3915.              as.remove(AccessibleState.SHOWING);
  3916.             }   
  3917.         }
  3918.                 if (parent.isCellSelected(row, column)) {
  3919.                 as.add(AccessibleState.SELECTED);
  3920.                 } else if (as.contains(AccessibleState.SELECTED)) {
  3921.             as.remove(AccessibleState.SELECTED);
  3922.                 }
  3923.         if ((row == getSelectedRow()) && (column == getSelectedColumn())) {
  3924.             as.add(AccessibleState.ACTIVE);
  3925.         }
  3926.             as.add(AccessibleState.TRANSIENT);
  3927.                 return as;
  3928.             }
  3929.  
  3930.             /**
  3931.              * Get the Accessible parent of this object.
  3932.              *
  3933.              * @return the Accessible parent of this object; null if this
  3934.              * object does not have an Accessible parent
  3935.              */
  3936.             public Accessible getAccessibleParent() {
  3937.                 return parent;
  3938.             }
  3939.  
  3940.             /**
  3941.              * Get the index of this object in its accessible parent.
  3942.              *
  3943.              * @return the index of this object in its parent; -1 if this
  3944.              * object does not have an accessible parent.
  3945.              * @see #getAccessibleParent
  3946.              */
  3947.             public int getAccessibleIndexInParent() {
  3948.                 return index;
  3949.             }
  3950.  
  3951.             /**
  3952.              * Returns the number of accessible children in the object.
  3953.              *
  3954.              * @return the number of accessible children in the object.
  3955.              */
  3956.             public int getAccessibleChildrenCount() {
  3957.                 AccessibleContext ac = getCurrentAccessibleContext();
  3958.                 if (ac != null) {
  3959.                     return ac.getAccessibleChildrenCount();
  3960.                 } else {
  3961.                     return 0;
  3962.                 }
  3963.             }
  3964.  
  3965.             /**
  3966.              * Return the specified Accessible child of the object.
  3967.              *
  3968.              * @param i zero-based index of child
  3969.              * @return the Accessible child of the object
  3970.              */
  3971.             public Accessible getAccessibleChild(int i) {
  3972.                 AccessibleContext ac = getCurrentAccessibleContext();
  3973.                 if (ac != null) {
  3974.                     Accessible accessibleChild = ac.getAccessibleChild(i);
  3975.                     ac.setAccessibleParent(this);
  3976.                     return accessibleChild;
  3977.                 } else {
  3978.                     return null;
  3979.                 }
  3980.             }
  3981.  
  3982.             /**
  3983.              * Gets the locale of the component. If the component does not have a
  3984.              * locale, then the locale of its parent is returned.
  3985.              *
  3986.              * @return This component's locale. If this component does not have a locale, the locale of its parent is returned.
  3987.              * @exception IllegalComponentStateException
  3988.              * If the Component does not have its own locale and has not yet been added to a containment hierarchy such that the locale can be
  3989.              * determined from the containing parent.
  3990.              * @see setLocale
  3991.              */
  3992.             public Locale getLocale() {
  3993.                 AccessibleContext ac = getCurrentAccessibleContext();
  3994.                 if (ac != null) {
  3995.                     return ac.getLocale();
  3996.                 } else {
  3997.                     return null;
  3998.                 }
  3999.             }
  4000.  
  4001.             /**
  4002.              * Add a PropertyChangeListener to the listener list.
  4003.              * The listener is registered for all properties.
  4004.              *
  4005.              * @param listener  The PropertyChangeListener to be added
  4006.              */
  4007.             public void addPropertyChangeListener(PropertyChangeListener l) {
  4008.                 AccessibleContext ac = getCurrentAccessibleContext();
  4009.                 if (ac != null) {
  4010.                     ac.addPropertyChangeListener(l);
  4011.                 } else {
  4012.                     super.addPropertyChangeListener(l);
  4013.                 }
  4014.             }
  4015.  
  4016.             /**
  4017.              * Remove a PropertyChangeListener from the listener list.
  4018.              * This removes a PropertyChangeListener that was registered
  4019.              * for all properties.
  4020.              *
  4021.              * @param listener  The PropertyChangeListener to be removed
  4022.              */
  4023.             public void removePropertyChangeListener(PropertyChangeListener l) {
  4024.                 AccessibleContext ac = getCurrentAccessibleContext();
  4025.                 if (ac != null) {
  4026.                     ac.removePropertyChangeListener(l);
  4027.                 } else {
  4028.                     super.removePropertyChangeListener(l);
  4029.                 }
  4030.             }
  4031.  
  4032.             /**
  4033.              * Get the AccessibleAction associated with this object if one
  4034.              * exists.  Otherwise return null.
  4035.              *
  4036.              * @return the AccessibleAction, or null
  4037.              */
  4038.             public AccessibleAction getAccessibleAction() {
  4039.                 return getCurrentAccessibleContext().getAccessibleAction();
  4040.             }
  4041.  
  4042.             /**
  4043.              * Get the AccessibleComponent associated with this object if one
  4044.              * exists.  Otherwise return null.
  4045.              *
  4046.              * @return the AccessibleComponent, or null
  4047.              */
  4048.             public AccessibleComponent getAccessibleComponent() {
  4049.                 return this; // to override getBounds()
  4050.             }
  4051.  
  4052.             /**
  4053.              * Get the AccessibleSelection associated with this object if one
  4054.              * exists.  Otherwise return null.
  4055.              *
  4056.              * @return the AccessibleSelection, or null
  4057.              */
  4058.             public AccessibleSelection getAccessibleSelection() {
  4059.                 return getCurrentAccessibleContext().getAccessibleSelection();
  4060.             }
  4061.  
  4062.             /**
  4063.              * Get the AccessibleText associated with this object if one
  4064.              * exists.  Otherwise return null.
  4065.              *
  4066.              * @return the AccessibleText, or null
  4067.              */
  4068.             public AccessibleText getAccessibleText() {
  4069.                 return getCurrentAccessibleContext().getAccessibleText();
  4070.             }
  4071.  
  4072.             /**
  4073.              * Get the AccessibleValue associated with this object if one
  4074.              * exists.  Otherwise return null.
  4075.              *
  4076.              * @return the AccessibleValue, or null
  4077.              */
  4078.             public AccessibleValue getAccessibleValue() {
  4079.                 return getCurrentAccessibleContext().getAccessibleValue();
  4080.             }
  4081.  
  4082.  
  4083.         // AccessibleComponent methods
  4084.  
  4085.             /**
  4086.              * Get the background color of this object.
  4087.              *
  4088.              * @return the background color, if supported, of the object;
  4089.              * otherwise, null
  4090.              */
  4091.             public Color getBackground() {
  4092.                 AccessibleContext ac = getCurrentAccessibleContext();
  4093.                 if (ac instanceof AccessibleComponent) {
  4094.                     return ((AccessibleComponent) ac).getBackground();
  4095.                 } else {
  4096.                     Component c = getCurrentComponent();
  4097.                     if (c != null) {
  4098.                         return c.getBackground();
  4099.                     } else {
  4100.                         return null;
  4101.                     }
  4102.                 }
  4103.             }
  4104.  
  4105.             /**
  4106.              * Set the background color of this object.
  4107.              *
  4108.              * @param c the new Color for the background
  4109.              */
  4110.             public void setBackground(Color c) {
  4111.                 AccessibleContext ac = getCurrentAccessibleContext();
  4112.                 if (ac instanceof AccessibleComponent) {
  4113.                     ((AccessibleComponent) ac).setBackground(c);
  4114.                 } else {
  4115.                     Component cp = getCurrentComponent();
  4116.                     if (cp != null) {
  4117.                         cp.setBackground(c);
  4118.                     }
  4119.                 }
  4120.             }
  4121.  
  4122.             /**
  4123.              * Get the foreground color of this object.
  4124.              *
  4125.              * @return the foreground color, if supported, of the object;
  4126.              * otherwise, null
  4127.              */
  4128.             public Color getForeground() {
  4129.                 AccessibleContext ac = getCurrentAccessibleContext();
  4130.                 if (ac instanceof AccessibleComponent) {
  4131.                     return ((AccessibleComponent) ac).getForeground();
  4132.                 } else {
  4133.                     Component c = getCurrentComponent();
  4134.                     if (c != null) {
  4135.                         return c.getForeground();
  4136.                     } else {
  4137.                         return null;
  4138.                     }
  4139.                 }
  4140.             }
  4141.  
  4142.             /**
  4143.              * Set the foreground color of this object.
  4144.              *
  4145.              * @param c the new Color for the foreground
  4146.              */
  4147.             public void setForeground(Color c) {
  4148.                 AccessibleContext ac = getCurrentAccessibleContext();
  4149.                 if (ac instanceof AccessibleComponent) {
  4150.                     ((AccessibleComponent) ac).setForeground(c);
  4151.                 } else {
  4152.                     Component cp = getCurrentComponent();
  4153.                     if (cp != null) {
  4154.                         cp.setForeground(c);
  4155.                     }
  4156.                 }
  4157.             }
  4158.  
  4159.             /**
  4160.              * Get the Cursor of this object.
  4161.              *
  4162.              * @return the Cursor, if supported, of the object; otherwise, null
  4163.              */
  4164.             public Cursor getCursor() {
  4165.                 AccessibleContext ac = getCurrentAccessibleContext();
  4166.                 if (ac instanceof AccessibleComponent) {
  4167.                     return ((AccessibleComponent) ac).getCursor();
  4168.                 } else {
  4169.                     Component c = getCurrentComponent();
  4170.                     if (c != null) {
  4171.                         return c.getCursor();
  4172.                     } else {
  4173.                         Accessible ap = getAccessibleParent();
  4174.                         if (ap instanceof AccessibleComponent) {
  4175.                             return ((AccessibleComponent) ap).getCursor();
  4176.                         } else {
  4177.                             return null;
  4178.                         }
  4179.                     }
  4180.                 }
  4181.             }
  4182.  
  4183.             /**
  4184.              * Set the Cursor of this object.
  4185.              *
  4186.              * @param c the new Cursor for the object
  4187.              */
  4188.             public void setCursor(Cursor c) {
  4189.                 AccessibleContext ac = getCurrentAccessibleContext();
  4190.                 if (ac instanceof AccessibleComponent) {
  4191.                     ((AccessibleComponent) ac).setCursor(c);
  4192.                 } else {
  4193.                     Component cp = getCurrentComponent();
  4194.                     if (cp != null) {
  4195.                         cp.setCursor(c);
  4196.                     }
  4197.                 }
  4198.             }
  4199.  
  4200.             /**
  4201.              * Get the Font of this object.
  4202.              *
  4203.              * @return the Font,if supported, for the object; otherwise, null
  4204.              */
  4205.             public Font getFont() {
  4206.                 AccessibleContext ac = getCurrentAccessibleContext();
  4207.                 if (ac instanceof AccessibleComponent) {
  4208.                     return ((AccessibleComponent) ac).getFont();
  4209.                 } else {
  4210.                     Component c = getCurrentComponent();
  4211.                     if (c != null) {
  4212.                         return c.getFont();
  4213.                     } else {
  4214.                         return null;
  4215.                     }
  4216.                 }
  4217.             }
  4218.  
  4219.             /**
  4220.              * Set the Font of this object.
  4221.              *
  4222.              * @param f the new Font for the object
  4223.              */
  4224.             public void setFont(Font f) {
  4225.                 AccessibleContext ac = getCurrentAccessibleContext();
  4226.                 if (ac instanceof AccessibleComponent) {
  4227.                     ((AccessibleComponent) ac).setFont(f);
  4228.                 } else {
  4229.                     Component c = getCurrentComponent();
  4230.                     if (c != null) {
  4231.                         c.setFont(f);
  4232.                     }
  4233.                 }
  4234.             }
  4235.  
  4236.             /**
  4237.              * Get the FontMetrics of this object.
  4238.              *
  4239.              * @param f the Font
  4240.              * @return the FontMetrics, if supported, the object; otherwise, null
  4241.              * @see getFont
  4242.              */
  4243.             public FontMetrics getFontMetrics(Font f) {
  4244.                 AccessibleContext ac = getCurrentAccessibleContext();
  4245.                 if (ac instanceof AccessibleComponent) {
  4246.                     return ((AccessibleComponent) ac).getFontMetrics(f);
  4247.                 } else {
  4248.                     Component c = getCurrentComponent();
  4249.                     if (c != null) {
  4250.                         return c.getFontMetrics(f);
  4251.                     } else {
  4252.                         return null;
  4253.                     }
  4254.                 }
  4255.             }
  4256.  
  4257.             /**
  4258.              * Determine if the object is enabled.
  4259.              *
  4260.              * @return true if object is enabled; otherwise, false
  4261.              */
  4262.             public boolean isEnabled() {
  4263.                 AccessibleContext ac = getCurrentAccessibleContext();
  4264.                 if (ac instanceof AccessibleComponent) {
  4265.                     return ((AccessibleComponent) ac).isEnabled();
  4266.                 } else {
  4267.                     Component c = getCurrentComponent();
  4268.                     if (c != null) {
  4269.                         return c.isEnabled();
  4270.                     } else {
  4271.                         return false;
  4272.                     }
  4273.                 }
  4274.             }
  4275.  
  4276.             /**
  4277.              * Set the enabled state of the object.
  4278.              *
  4279.              * @param b if true, enables this object; otherwise, disables it
  4280.              */
  4281.             public void setEnabled(boolean b) {
  4282.                 AccessibleContext ac = getCurrentAccessibleContext();
  4283.                 if (ac instanceof AccessibleComponent) {
  4284.                     ((AccessibleComponent) ac).setEnabled(b);
  4285.                 } else {
  4286.                     Component c = getCurrentComponent();
  4287.                     if (c != null) {
  4288.                         c.setEnabled(b);
  4289.                     }
  4290.                 }
  4291.             }
  4292.  
  4293.             /**
  4294.              * Determine if the object is visible.  Note: this means that the
  4295.              * object intends to be visible; however, it may not in fact be
  4296.              * showing on the screen because one of the objects that this object
  4297.              * is contained by is not visible.  To determine if an object is
  4298.              * showing on the screen, use isShowing().
  4299.              *
  4300.              * @return true if object is visible; otherwise, false
  4301.              */
  4302.             public boolean isVisible() {
  4303.                 AccessibleContext ac = getCurrentAccessibleContext();
  4304.                 if (ac instanceof AccessibleComponent) {
  4305.                     return ((AccessibleComponent) ac).isVisible();
  4306.                 } else {
  4307.                     Component c = getCurrentComponent();
  4308.                     if (c != null) {
  4309.                         return c.isVisible();
  4310.                     } else {
  4311.                         return false;
  4312.                     }
  4313.                 }
  4314.             }
  4315.  
  4316.             /**
  4317.              * Set the visible state of the object.
  4318.              *
  4319.              * @param b if true, shows this object; otherwise, hides it
  4320.              */
  4321.             public void setVisible(boolean b) {
  4322.                 AccessibleContext ac = getCurrentAccessibleContext();
  4323.                 if (ac instanceof AccessibleComponent) {
  4324.                     ((AccessibleComponent) ac).setVisible(b);
  4325.                 } else {
  4326.                     Component c = getCurrentComponent();
  4327.                     if (c != null) {
  4328.                         c.setVisible(b);
  4329.                     }
  4330.                 }
  4331.             }
  4332.  
  4333.             /**
  4334.              * Determine if the object is showing.  This is determined by checking
  4335.              * the visibility of the object and ancestors of the object.  Note: this
  4336.              * will return true even if the object is obscured by another (for example,
  4337.              * it happens to be underneath a menu that was pulled down).
  4338.              *
  4339.              * @return true if object is showing; otherwise, false
  4340.              */
  4341.             public boolean isShowing() {
  4342.                 AccessibleContext ac = getCurrentAccessibleContext();
  4343.                 if (ac instanceof AccessibleComponent) {
  4344.                     return ((AccessibleComponent) ac).isShowing();
  4345.                 } else {
  4346.                     Component c = getCurrentComponent();
  4347.                     if (c != null) {
  4348.                         return c.isShowing();
  4349.                     } else {
  4350.                         return false;
  4351.                     }
  4352.                 }
  4353.             }
  4354.  
  4355.             /**
  4356.              * Checks whether the specified point is within this object's bounds,
  4357.              * where the point's x and y coordinates are defined to be relative to the
  4358.              * coordinate system of the object.
  4359.              *
  4360.              * @param p the Point relative to the coordinate system of the object
  4361.              * @return true if object contains Point; otherwise false
  4362.              */
  4363.             public boolean contains(Point p) {
  4364.                 AccessibleContext ac = getCurrentAccessibleContext();
  4365.                 if (ac instanceof AccessibleComponent) {
  4366.                     Rectangle r = ((AccessibleComponent) ac).getBounds();
  4367.                     return r.contains(p);
  4368.                 } else {
  4369.                     Component c = getCurrentComponent();
  4370.                     if (c != null) {
  4371.                         Rectangle r = c.getBounds();
  4372.                         return r.contains(p);
  4373.                     } else {
  4374.                         return getBounds().contains(p);
  4375.                     }
  4376.                 }
  4377.             }
  4378.  
  4379.             /**
  4380.              * Returns the location of the object on the screen.
  4381.              *
  4382.              * @return location of object on screen -- can be null if this object
  4383.              * is not on the screen
  4384.              */
  4385.             public Point getLocationOnScreen() {
  4386.                 if (parent != null) {
  4387.                     Point parentLocation = parent.getLocationOnScreen();
  4388.                     Point componentLocation = getLocation();
  4389.                     componentLocation.translate(parentLocation.x, parentLocation.y);
  4390.                     return componentLocation;
  4391.                 } else {
  4392.                     return null;
  4393.                 }
  4394.             }
  4395.  
  4396.             /**
  4397.              * Gets the location of the object relative to the parent in the form
  4398.              * of a point specifying the object's top-left corner in the screen's
  4399.              * coordinate space.
  4400.              *
  4401.              * @return An instance of Point representing the top-left corner of the
  4402.              * objects's bounds in the coordinate space of the screen; null if
  4403.              * this object or its parent are not on the screen
  4404.              */
  4405.             public Point getLocation() {
  4406.                 if (parent != null) {
  4407.                     Rectangle r = parent.getCellRect(row, column, false);
  4408.                     if (r != null) {
  4409.                         return r.getLocation();
  4410.                     }
  4411.                 }
  4412.                 return null;
  4413.             }
  4414.  
  4415.             /**
  4416.              * Sets the location of the object relative to the parent.
  4417.              */
  4418.             public void setLocation(Point p) {
  4419. //              if ((parent != null)  && (parent.contains(p))) {
  4420. //                  ensureIndexIsVisible(indexInParent);
  4421. //              }
  4422.             }
  4423.  
  4424.             public Rectangle getBounds() {
  4425.                 if (parent != null) {
  4426.                     return parent.getCellRect(row, column, false);
  4427.                 } else {
  4428.                     return null;
  4429.                 }
  4430.             }
  4431.  
  4432.             public void setBounds(Rectangle r) {
  4433.                 AccessibleContext ac = getCurrentAccessibleContext();
  4434.                 if (ac instanceof AccessibleComponent) {
  4435.                     ((AccessibleComponent) ac).setBounds(r);
  4436.                 } else {
  4437.                     Component c = getCurrentComponent();
  4438.                     if (c != null) {
  4439.                         c.setBounds(r);
  4440.                     }
  4441.                 }
  4442.             }
  4443.  
  4444.             public Dimension getSize() {
  4445.                 if (parent != null) {
  4446.                     Rectangle r = parent.getCellRect(row, column, false);
  4447.                     if (r != null) {
  4448.                         return r.getSize();
  4449.                     }
  4450.                 }
  4451.                 return null;
  4452.             }
  4453.  
  4454.             public void setSize (Dimension d) {
  4455.                 AccessibleContext ac = getCurrentAccessibleContext();
  4456.                 if (ac instanceof AccessibleComponent) {
  4457.                     ((AccessibleComponent) ac).setSize(d);
  4458.                 } else {
  4459.                     Component c = getCurrentComponent();
  4460.                     if (c != null) {
  4461.                         c.setSize(d);
  4462.                     }
  4463.                 }
  4464.             }
  4465.  
  4466.             public Accessible getAccessibleAt(Point p) {
  4467.                 AccessibleContext ac = getCurrentAccessibleContext();
  4468.                 if (ac instanceof AccessibleComponent) {
  4469.                     return ((AccessibleComponent) ac).getAccessibleAt(p);
  4470.                 } else {
  4471.                     return null;
  4472.                 }
  4473.             }
  4474.  
  4475.             public boolean isFocusTraversable() {
  4476.                 AccessibleContext ac = getCurrentAccessibleContext();
  4477.                 if (ac instanceof AccessibleComponent) {
  4478.                     return ((AccessibleComponent) ac).isFocusTraversable();
  4479.                 } else {
  4480.                     Component c = getCurrentComponent();
  4481.                     if (c != null) {
  4482.                         return c.isFocusTraversable();
  4483.                     } else {
  4484.                         return false;
  4485.                     }
  4486.                 }
  4487.             }
  4488.  
  4489.             public void requestFocus() {
  4490.                 AccessibleContext ac = getCurrentAccessibleContext();
  4491.                 if (ac instanceof AccessibleComponent) {
  4492.                     ((AccessibleComponent) ac).requestFocus();
  4493.                 } else {
  4494.                     Component c = getCurrentComponent();
  4495.                     if (c != null) {
  4496.                         c.requestFocus();
  4497.                     }
  4498.                 }
  4499.             }
  4500.  
  4501.             public void addFocusListener(FocusListener l) {
  4502.                 AccessibleContext ac = getCurrentAccessibleContext();
  4503.                 if (ac instanceof AccessibleComponent) {
  4504.                     ((AccessibleComponent) ac).addFocusListener(l);
  4505.                 } else {
  4506.                     Component c = getCurrentComponent();
  4507.                     if (c != null) {
  4508.                         c.addFocusListener(l);
  4509.                     }
  4510.                 }
  4511.             }
  4512.  
  4513.             public void removeFocusListener(FocusListener l) {
  4514.                 AccessibleContext ac = getCurrentAccessibleContext();
  4515.                 if (ac instanceof AccessibleComponent) {
  4516.                     ((AccessibleComponent) ac).removeFocusListener(l);
  4517.                 } else {
  4518.                     Component c = getCurrentComponent();
  4519.                     if (c != null) {
  4520.                         c.removeFocusListener(l);
  4521.                     }
  4522.                 }
  4523.             }
  4524.  
  4525.         } // inner class AccessibleJTableCell
  4526.  
  4527.     }  // inner class AccessibleJTable
  4528.  
  4529. }  // End of Class JTable
  4530.